Introduction
In this RMarkdown file, the extended methods and data-analysis for the manuscript “Multisystem inflammatory syndrome in children related to COVID-19: a systematic review” is described. The complete data-analysis can be reproduced from the data collection sheet (in .xls format), provided in the supplementary files of the manuscript or on Github .
Prior to conducting the review, the study protocol was published on the PROSPERO systematic review register (CRD42020189248) .
knitr:: opts_chunk$ set (cache = FALSE , warning = FALSE , message = FALSE )
options (digits = 3 )
library (tidyverse)
require (readxl)
require (httr)
require (reshape2)
require (broom)
require (RColorBrewer)
require (scales)
require (ggrepel)
require (gridExtra)
require (ggExtra)
library (ggbeeswarm)
require (ggpubr)
library (cowplot)
library (naniar)
require (DT)
require (zoo)
require (psych)
library (skimr)
library (UpSetR)
library (see)
library (wesanderson)
options (scipen= 999 )
co_hb <- 12
co_neutrophilia <- 8000
co_CRP <- 10
co_lympho <- 1250
co_fibrino <- 400
co_Ddim <- 250
co_ferritin <- 300
co_albu <- 34
co_PCT <- 0.49
co_LDH <- 280
co_IL6 <- 16.4
co_ESR <- 22
co_BNP <- 100
co_NTproBNP <- 400
co_tropo <- 40
co_WBC <- 11000
co_platelet <- 150000
co_sodium <- 135
#input = df_cohort_controls
#find = "max"
#param = "CRP"
collapse_labvals_cohort <- function (input, find, param, verbose = FALSE ){
if (find == "max" ){
df <- input %>% select (contains (param) | contains ("cohort_id" ) | contains ("cohort_type" ) | contains ("tot_cases_n" ))
if (verbose == TRUE ){
print ("Column extracted from cohorts:" )
print (colnames (df))
}
df_med <- df %>% select (contains ("med" ))
df_med <- type_convert (df_med)
df_med <- df_med %>% mutate_all (funs (replace_na (., -999 )))
# colnames(df_med)[max.col(df_med,ties.method="first")]
df_med <- df_med %>% mutate (med = as.numeric (apply (df_med, 1 , max)))
df_min <- df %>% select (contains ("Q1" ))
df_min <- type_convert (df_min)
df_min <- df_min %>% mutate_all (funs (replace_na (., 0 )))
#colnames(df_min)[max.col(df_min,ties.method="first")]
df_min <- df_min %>% mutate (min = as.numeric (apply (df_min, 1 , max)))
df_max <- df %>% select (contains ("Q3" ))
df_max <- type_convert (df_max)
df_max <- df_max %>% mutate_all (funs (replace_na (., 0 )))
#colnames(df_max)[max.col(df_max,ties.method="first")]
df_max <- df_max %>% mutate (max = as.numeric (apply (df_max, 1 , max)))
df_full <- cbind (df %>% select (cohort_id, cohort_type, tot_cases_n), df_med %>% select (med), df_min %>% select (min), df_max %>% select (max))
df_full[df_full == -999 ] <- NA
names (df_full)[names (df_full) == 'max' ] <- paste0 (param, "_max" )
names (df_full)[names (df_full) == 'min' ] <- paste0 (param, "_min" )
names (df_full)[names (df_full) == 'med' ] <- paste0 (param, "_med" )
df_full$ data_descr <- "IQR"
df_full$ cohort_id <- paste0 (df_full$ cohort_id, " (n = " , as.character (df_full$ tot_cases_n),")" )
write.csv (df_full, paste0 ("./data/cohort_" , param, ".csv" ))
print (datatable (df_full, caption = paste0 ("overview of " , param)))
return (df_full)
}
else if (find == "min" ){
df <- input %>% select (contains (param) | contains ("cohort_id" ) | contains ("cohort_type" ) | contains ("tot_cases_n" ))
if (verbose == TRUE ){
print ("Column extracted from cohorts:" )
print (colnames (df))
}
df_med <- df %>% select (contains ("med" ))
df_med <- type_convert (df_med)
df_med <- df_med %>% mutate_all (funs (replace_na (., 1e6 )))
# colnames(df_med)[max.col(df_med,ties.method="first")]
df_med <- df_med %>% mutate (med = as.numeric (apply (df_med, 1 , min)))
df_min <- df %>% select (contains ("Q1" ))
df_min <- type_convert (df_min)
df_min <- df_min %>% mutate_all (funs (replace_na (., 1e6 )))
#colnames(df_min)[max.col(df_min,ties.method="first")]
df_min <- df_min %>% mutate (min = as.numeric (apply (df_min, 1 , min)))
df_max <- df %>% select (contains ("Q3" ))
df_max <- type_convert (df_max)
df_max <- df_max %>% mutate_all (funs (replace_na (., 1e6 )))
#colnames(df_max)[max.col(df_max,ties.method="first")]
df_max <- df_max %>% mutate (max = as.numeric (apply (df_max, 1 , min)))
df_full <- cbind (df %>% select (cohort_id, cohort_type, tot_cases_n), df_med %>% select (med), df_min %>% select (min), df_max %>% select (max))
df_full[df_full == 1e6 ] <- NA
names (df_full)[names (df_full) == 'max' ] <- paste0 (param, "_max" )
names (df_full)[names (df_full) == 'min' ] <- paste0 (param, "_min" )
names (df_full)[names (df_full) == 'med' ] <- paste0 (param, "_med" )
df_full$ data_descr <- "IQR"
df_full$ cohort_id <- paste0 (df_full$ cohort_id, " (n = " , as.character (df_full$ tot_cases_n),")" )
write.csv (df_full, paste0 ("./data/cohort_" , param, ".csv" ))
print (datatable (df_full, caption = paste0 ("overview of " , param)))
return (df_full)
}
}
#input = df_singlecases
#find = "max"
#param = "CRP"
collapse_labvals_single <- function (input, find, param, verbose = FALSE ){
if (find == "max" ){
df <- input %>% select (contains (param) | contains ("cohort_id" ))
if (verbose == TRUE ){
print ("Column extracted from single cases:" )
print (colnames (df))
}
df_coll <- df %>% mutate_all (funs (replace_na (., -999 )))
df_coll <- type_convert (df_coll)
# colnames(df_med)[max.col(df_med,ties.method="first")]
df_coll <- df_coll %>% mutate (max = as.numeric (apply (df_coll, 1 , max)))
df_coll[df_coll == -999 ] <- NA
names (df_coll)[names (df_coll) == 'max' ] <- paste0 (param, "_max" )
df_coll$ data_descr <- "IQR"
df_coll$ cohort_id <- paste0 ("single cases (n = " , as.character (n_single_cases),")" )
write.csv (skim (df_coll), paste0 ("./data/singlecases_" , param, ".csv" ))
return (df_coll)
}
else if (find == "min" ){
df <- input %>% select (contains (param) | contains ("cohort_id" ))
if (verbose == TRUE ){
print ("Column extracted from single cases:" )
print (colnames (df))
}
df_coll <- df %>% mutate_all (funs (replace_na (., 1e6 )))
# colnames(df_med)[max.col(df_med,ties.method="first")]
df_coll <- df_coll %>% mutate (min = as.numeric (apply (df_coll, 1 , min)))
df_coll[df_coll == 1e6 ] <- NA
names (df_coll)[names (df_coll) == 'min' ] <- paste0 (param, "_min" )
df_coll$ cohort_id <- paste0 ("single cases (n = " , as.character (n_single_cases),")" )
write.csv (skim (df_coll), paste0 ("./data/singlecases_" , param, ".csv" ))
return (df_coll)
}
}
moveme <- function (df, movecommand) {
invec <- names (df)
movecommand <- lapply (strsplit (strsplit (movecommand, ";" )[[1 ]],
",| \\ s+" ), function (x) x[x != "" ])
movelist <- lapply (movecommand, function (x) {
Where <- x[which (x %in% c ("before" , "after" , "first" ,
"last" )): length (x)]
ToMove <- setdiff (x, Where)
list (ToMove, Where)
})
myVec <- invec
for (i in seq_along (movelist)) {
temp <- setdiff (myVec, movelist[[i]][[1 ]])
A <- movelist[[i]][[2 ]][1 ]
if (A %in% c ("before" , "after" )) {
ba <- movelist[[i]][[2 ]][2 ]
if (A == "before" ) {
after <- match (ba, temp) - 1
}
else if (A == "after" ) {
after <- match (ba, temp)
}
}
else if (A == "first" ) {
after <- 0
}
else if (A == "last" ) {
after <- length (myVec)
}
myVec <- append (temp, values = movelist[[i]][[1 ]], after = after)
}
df[,match (myVec, names (df))]
}
makeBarplot <- function (var_id_cohort, var_id_single, var_id){
n_cohort <- df_cohort %>% select (tot_cases_n) %>% sum ()#, outcome_death_n)
var_cohort <- df_cohort[var_id_cohort] %>% sum (., na.rm = TRUE )#, outcome_death_n)
n_single <- df_singlecases %>% nrow ()
var_single <- df_singlecases %>% filter (get (var_id_single) == TRUE ) %>% nrow ()
n_all <- n_cohort + n_single
var_all <- var_cohort + var_single
bar_df_abs <- data.frame (x = c ("cohort" , "cohort" , "single cases" , "single cases" , "all" , "all" ), col = c ("total" , var_id, "total" , var_id, "total" , var_id), vals = c (n_cohort, var_cohort, n_single, var_single, n_all, var_all) )
bar_df_prct <- data.frame (x = c ("cohort" , "cohort" , "single cases" , "single cases" , "all" , "all" ), col = c (paste0 (var_id, " -" ), paste0 (var_id, " +" ), paste0 (var_id, " -" ), paste0 (var_id, " +" ), paste0 (var_id, " -" ), paste0 (var_id, " +" )), vals = c (100 - (var_cohort/ n_cohort* 100 ), var_cohort/ n_cohort* 100 , 100 - (var_single/ n_single* 100 ), var_single/ n_single* 100 , 100 - (var_all/ n_all* 100 ), var_all/ n_all* 100 ) )
p_abs <- ggplot (bar_df_abs, aes (x = x, y = vals, fill = col)) +
geom_bar (stat = "identity" , position = "dodge" ) +
theme_bw () +
labs (title = paste0 ("Total cases vs " , var_id), subtitle = "Absolute numbers" , x = "group" , y = "n" , col = "" ) +
scale_fill_manual (values = wes_palette ("Royal1" ))
p_prct <- ggplot (bar_df_prct, aes (x = x, y = vals, fill = col)) +
geom_bar (stat = "identity" , position = "fill" ) +
theme_bw () +
labs (title = paste0 (var_id), subtitle = "Percent" , x = "group" , y = "%" , col = "" ) +
scale_y_continuous (labels = scales:: percent)+
scale_fill_manual (values = wes_palette ("Royal1" ))
ggarrange (p_abs, p_prct, legend = "bottom" )
}
makeHeatmap_cohort <- function (param1, colname_single, exclude_single = NULL , plottitle, textsize = 3 ){
var_cohort <- df_cohort %>% select (("cohort_id" ) | "tot_cases_n" | ( contains (param1) & contains ("_n" )))
var_cohort$ cohort_id <- paste0 (var_cohort$ cohort_id, " (n = " , as.character (var_cohort$ tot_cases_n),")" )
var_cohort <- var_cohort %>%
gather (variable, value, 3 : ncol (var_cohort)) %>% group_by (cohort_id, variable) %>% summarize (prct = value/ tot_cases_n* 100 )
var_cohort$ variable <- sub ("_n" , "" , var_cohort$ variable)
if (! is.null (exclude_single)){
var_single <- df_singlecases %>% select (- contains (exclude_single))
var_single <- var_single %>% select (contains (colname_single))
} else
{
var_single <- df_singlecases %>% select (contains (colname_single))
}
#%>% select(-contains("any"))
cols <- sapply (var_single, is.logical)
var_single[,cols] <- lapply (var_single[,cols], as.numeric)
var_single <- colSums (var_single, na.rm = TRUE )
var_single <- var_single/ nrow (df_singlecases)* 100
var_single <- as.data.frame (var_single) %>% rownames_to_column ()
var_single$ cohort_id <- paste0 ("single cases (n = " , n_single_cases,")" )
colnames (var_single) <- c ("variable" , "prct" , "cohort_id" )
missing <- setdiff (var_single$ variable, var_cohort$ variable)
if (length (missing) != 0 ){
missing_df <- data.frame (variable = missing, prct = NA , cohort_id = unique (var_cohort$ cohort_id))
var_cohort <- bind_rows (var_cohort, as_tibble (missing_df))
} else if (length (missing) == 0 ) {
missing <- setdiff (var_cohort$ variable, var_single$ variable)
if (length (missing) != 0 ){
missing_df <- data.frame (variable = missing, prct = NA , cohort_id = unique (var_single$ cohort_id))
var_single <- bind_rows (var_single, as_tibble (missing_df))
}
}
hm_cohort <- ggplot (var_cohort, aes (x = variable, y = cohort_id, fill = prct)) +
geom_tile () + theme_classic () +
theme (axis.text.x= element_blank (), axis.ticks.x= element_blank (), axis.line= element_blank ())+
scale_fill_gradient (low = "yellow" , high= "red" , na.value = "lightgray" , limits = c (0 ,100 )) +
labs (x = "" , y = "cohort" , title = plottitle) +
geom_text (aes (label= round (prct, 2 )), size = textsize, color = "black" )
hm_single <- ggplot (var_single, aes (x = variable, y = cohort_id, fill = prct)) +
geom_tile () + theme_classic () +
theme (axis.text.x= element_text (angle= 90 , hjust= 1 ), axis.line= element_blank ())+
scale_fill_gradient (low = "yellow" , high = "red" , na.value = "lightgray" , limits = c (0 ,100 ))+ labs (y = "cohort" ) +
geom_text (aes (label= round (prct, 2 )), size = textsize, color = "black" )
plot_grid (hm_cohort, hm_single, align = "v" , nrow = 2 , rel_heights = c (1 / 2 , 1 / 2 ))
}
Search strategy
Electronic bibliographical databases were searched, both indexed (PubMed, Embase) and preprint repositories (BioRxiv and MedRxiv). Additionally, COVID-19-specific research repositories were be searched (Cochrane COVID‐19 Study Register, the World Health Organization (WHO) COVID‐19 Global Research Database). Publications in English language between 31 December 2019 up to 30 June 2020, when the final search was carried out, were reviewed on eligibility. Both finished and ongoing studies were considered. The reference lists of the included studies were considered as an additional source.
Search strategy focused on keywords involving the hyperinflammatory presentation (PIMS-TS, MIS-C, hyperinflammation, HLH, toxic shock syndrome, vasculitis, Kawasaki disease), as well as the association with COVID-19 (SARS-CoV-2, COVID-19, novel coronavirus) and the pediatric population (children, adolescent, pediatric). Structured hierarchic keywords (MeSH, Emtree) and wildcards were used when applicable. Boolean operators were used to combine the various keywords of interest. Below, the full search terms are presented for the different databases).
PubMed
(“PIMS*” OR “MIS*” OR “multisystem inflammat*” OR “hyperinflammat*” OR “inflammatory disease” OR “systemic inflammat*” OR “cytokine release” OR “Kawasaki*” OR “vasculitis” OR “toxic shock” OR “shock” OR ("pediatric multisystem inflammatory disease, COVID-19 related" [Supplementary Concept]) OR "Mucocutaneous Lymph Node Syndrome"[Mesh] OR "Shock"[Mesh] OR "Vasculitis"[Mesh] OR “inflammation”[MeSH]) AND (“covid*” or “sars-cov-2” or “2019-nCov” or “novel coronavirus” or “coronavirus disease” or "COVID-19" [Supplementary Concept] OR "severe acute respiratory syndrome coronavirus 2" [Supplementary Concept]) AND (“child*” or “adolescen*” or “teen*” or “pediatric*” or “infant” or “newborn” or "Child"[Mesh] OR "Adolescent"[Mesh] OR "Pediatrics"[Mesh] or "Infant, Newborn"[Mesh] or "Infant"[Mesh]) AND ("2019/12/31"[Date - Publication] : "3000"[Date - Publication])
Embase
('pims*' OR 'mis' OR ‘mis-c’ OR 'multisystem inflammat*' OR 'hyperinflammat*' OR 'inflammatory disease' OR 'systemic inflammat*' OR 'cytokine release' OR 'kawasaki*' OR 'vasculitis' OR 'toxic shock' OR 'shock') AND ('covid*' OR 'sars-cov-2' OR '2019-ncov' OR 'novel coronavirus' OR 'coronavirus disease') AND ('child*' OR 'adolescen*' OR 'teen*' OR 'pediatric*' OR 'infant' OR 'newborn') AND [31-12-2019]/sd
BioRxiv and MedRxiv
Literature search in biorxiv and medrxiv was done with the R by downloading the data from the dedicated COVID-19 SARS-CoV-2 preprints page in json format, and can be found on Github .
Cochrane COVID-19 study register
(pims* OR mis OR "mis-c" OR "multisystem inflammat*" OR hyperinflammat* OR "inflammatory disease" OR "systemic inflammat*" OR "cytokine release" OR kawasaki* OR vasculitis OR "toxic shock" OR shock) AND (child* OR adolescen* OR teen* OR pediatric* OR infant OR newborn)
WHO COVID-19 Global literature on coronavirus disease
("pims*" OR "mis" OR "mis-c" OR "multisystem inflammat*" OR "hyperinflammat*" OR "inflammatory disease" OR "systemic inflammat*" OR "cytokine release" OR "kawasaki*" OR "vasculitis" OR "toxic shock" OR "shock") AND ("child*" OR "adolescen*" OR "teen*" OR "pediatric*" OR "infant" OR "newborn")
Study selection and risk of bias assessment
Original studies were included with following designs: RCT, observational studies, case-control studies, cross-sectional studies, case reports and case series.
Records eligible for inclusion should present clinical cases fulfilling the following 3 criteria:
Inclusion criteria
Study population: hyperinflammatory syndrome meeting the case definitions of PIMS-TS or MIS(-C) in children (0-19 years of age) with a temporal association with confirmed or probable COVID-19
Outcome: clinical, epidemiological and immunological descriptions, therapeutic management and clinical effect, and prognosis of individuals or cohorts of patients.
Types of study designs: RCT, observational studies, case-control studies, cross-sectional studies, case reports and case series
Exclusion criteria 1. Studies on adult patients with SARS-CoV-2 infection and/or SARS-CoV-2 associated hyperinflammatory syndromes 2. Studies on pediatric patients with other coronavirus infections (SARS-CoV-1 and Middle East Respiratory Syndrome Coronavirus (MERS-CoV) infection or other respiratory infections. 3. Studies with incomplete or lacking necessary data 4. Duplicate studies 5. Studies without accessible full text versions 6. Studies not in English language
Study selection was a two-stage process with, first, titles and abstracts of studies screened with retrieval using the search strategy and then, second, full text screening of potentially eligible studies assessed by two reviewers independently. Any disagreement over the eligibility of particular studies was resolved through discussion with a third reviewer.
The Preferred Reporting Items for Systematic Reviews and Meta-Analyses (PRISMA) checklist was used to guide the study selection and extraction process. Risk for bias on eligible observational studies were assessed by LH according to the NewCastle-Ottawa Scale (NOS), with full verification of all judgments by RVP. Level of evidence was rated according to Sackett.
PRISMA flow diagram
Data import and cleaning
Single cases
After data collection, we import the single cases from the general excel sheet and transform the excel sheet so that variables are columns and rows are cases. Columns without any values are also removed.
The single cases from Pouletty (10.1136/annrheumdis-2020-217960) are excluded (as they are included in the cohorts).
df_singlecases <-
read_excel ("/Users/rmvpaeme/Onedrive/UGent/PIMS-TS Systematic Review - Data extractie/data extractie.xlsx" ,
sheet = "Single cases" ,
skip = 1 ,
col_names = FALSE )[,- c (1 : 2 )]
df_singlecases <- df_singlecases %>% t ()
df_singlecases <- as.data.frame (df_singlecases, stringsAsFactors = FALSE )
nms <- as.vector (df_singlecases[1 ,])
nms[is.na (nms)] <- 'tmp'
colnames (df_singlecases) <- make.unique (as.character (nms))
df_singlecases <- df_singlecases[- 1 ,]
df_singlecases <- df_singlecases %>% select (- contains ("tmp" ))
df_singlecases <- df_singlecases %>% select (- variable_id)
df_singlecases <- df_singlecases %>%
mutate_all (funs (str_replace (., "Yes" , "yes" )))
df_singlecases <- df_singlecases %>%
mutate_all (funs (str_replace (., "No" , "no" )))
df_singlecases <- df_singlecases %>%
mutate_all (funs (str_replace (., "pos" , "yes" )))
df_singlecases <- df_singlecases %>%
mutate_all (funs (str_replace (., "neg" , "no" )))
df_singlecases <- df_singlecases %>%
replace_with_na_all (condition = ~ .x == "NA" )
df_singlecases <- type_convert (df_singlecases)
df_singlecases_inclPouletty <- df_singlecases
df_singlecases <- df_singlecases %>% filter (doi != "https://10.1136/annrheumdis-2020-217960" ) # these cases are excluded according to the data sheet
df_singlecases <- df_singlecases[colSums (! is.na (df_singlecases)) > 0 ]
n_single_cases <- nrow (df_singlecases)
Making summary statistics
In this section, data is summarized. For example, if there are any comorbidities present, a column “comorb_any” is added and annotated as TRUE. The same is done for COVID serology and symptoms of major organ (respiratory, cardiovascular etc).
If IgG, IgA, IgM or COVID serology is reported as positive, the column covid_sero_any is annotated as TRUE.
If PCR+, stool PCR+, IgG, IgA, IgM or COVID serology is reported as positive, the column covid_pos_any is annotated as TRUE.
If any respiratory symptoms, symp_resp_any is annotated as TRUE.
If any GI symptoms, symp_GI_any is annotated as TRUE.
If any neurological symptoms, symp_neuro_any is annotated as TRUE.
If any renal symptoms, symp_renal_any is annotated as TRUE.
If any cardiovascular symptoms, symp_cardiovasc_any is annotated as TRUE.
df_singlecases <- df_singlecases %>% mutate (symp_cardiovasc_any = apply (df_singlecases %>% select (symp_cardiovasc_myocard,
symp_cardiovasc_pericard,
symp_cardiovasc_cordilat,
symp_cardiovasc_aneurysm,
symp_cardiovasc_shock,
symp_cardiovasc_tachycard,
symp_cardiovasc_arrhyt), 1 , any))
df_singlecases <- df_singlecases %>% moveme (., "symp_cardiovasc_any before symp_cardiovasc_myocard" )
write.csv (df_singlecases, paste0 ("./data/df_singlecases.csv" ))
#datatable(df_singlecases, caption = "Single cases dataframe")
Download single case data as .csv on Github
Cohorts
Afterwards, we do the same for the cohort sheet.
The papers by Grimaud et al. and Verdoni et al. are removed from the cohort dataframe, as most information is present in the single cases dataframe.
df_cohort <-
read_excel ("/Users/rmvpaeme/Onedrive/UGent/PIMS-TS Systematic Review - Data extractie/data extractie.xlsx" ,
sheet = "Cohorts" ,
skip = 1 ,
col_names = FALSE )[,- c (1 : 3 )]
df_cohort <- df_cohort %>% t ()
df_cohort <- as.data.frame (df_cohort, stringsAsFactors = FALSE )
nms <- as.vector (df_cohort[1 ,])
nms[is.na (nms)] <- 'tmp'
colnames (df_cohort) <- make.unique (as.character (nms))
df_cohort <- df_cohort[- 1 ,]
df_cohort <- df_cohort %>% select (- contains ("tmp" ))
df_cohort <- df_cohort %>% select (- variable_id)
df_cohort <- df_cohort %>%
mutate_all (funs (str_replace (., "Yes" , "yes" )))
df_cohort <- df_cohort %>%
mutate_all (funs (str_replace (., "No" , "no" )))
df_cohort <- df_cohort %>%
mutate_all (funs (str_replace (., "pos" , "yes" )))
df_cohort <- df_cohort %>%
mutate_all (funs (str_replace (., "neg" , "no" )))
df_cohort <- df_cohort %>%
replace_with_na_all (condition = ~ .x == "NA" )
df_cohort <- type_convert (df_cohort)
df_cohort <- df_cohort[colSums (! is.na (df_cohort)) > 0 ]
df_cohort <- df_cohort %>% filter (doi != "https://doi.org/10.1186/s13613-020-00690-8" ) %>% filter (doi != "https://doi.org/10.1016/S0140-6736(20)31103-X" )
df_cohort_controls <- df_cohort
df_cohort <- df_cohort %>% filter (cohort_type == "covid" )
write.csv (df_cohort, paste0 ("./data/df_cohort.csv" ))
#datatable(df_cohort, caption = "Cohort dataframe")
Download cohort data as .csv on Github
Descriptive statistics
General
Click on the any of the tabs above to see descriptive statistics for every variable
Single cases
How to read
Under “Variable type: logical”, the number of true/falses are depicted. E.g. at the top we can see that there are 95 number of rows (= 95 patients). Overweight has 79 missing values (17% is complete), which means that 95-79=16 patients have either “TRUE” or “FALSE” for overweight. Of these 16, 9 are marked as “TRUE” for overweight.
Download data as .csv on Github
Cohorts
How to read
The sum column equals the sum of all individuals, e.g. sum(tot_cases_n) means that there are 592 patients in total in the cohorts; sum(outcome_death_n) means that 9 patients died.
The “Prct_total” column is the percentage of e.g. death (9/592). Only makes sense where n is reported e.g. therapy (not for lab values).
Download data as .csv on Github
Historical controls
Download data as .csv on Github
Data exploration
Total cases and deaths
Sex
n_cohort <- df_cohort %>% select (tot_cases_n) %>% sum ()
var_cohort <- df_cohort %>% select (contains ("sex" ))
var_cohort <- colSums (var_cohort, na.rm = TRUE )
var_cohort <- var_cohort/ sum (df_cohort$ tot_cases_n)* 100
var_cohort["sex_na" ] <- (100 - var_cohort["sex_m" ] - var_cohort["sex_f" ])
var_control <- df_cohort_controls %>% filter (cohort_id == "Pouletty - control" ) %>% select (contains ("sex" ))
var_control <- colSums (var_control, na.rm = TRUE )
var_control <- var_control/ sum (df_cohort_controls %>% filter (cohort_id == "Pouletty - control" ) %>% select (tot_cases_n))* 100
var_control["sex_na" ] <- (100 - var_control["sex_m" ] - var_control["sex_f" ])
n_single <- df_singlecases %>% nrow ()
var_single <- df_singlecases %>% select (contains ("sex" ))
var_single$ sex_m <- ifelse (var_single$ sex == "M" , TRUE , FALSE )
var_single$ sex_f <- ifelse (var_single$ sex == "F" , TRUE , FALSE )
cols <- sapply (var_single, is.logical)
var_single[,cols] <- lapply (var_single[,cols], as.numeric)
var_single <- colSums (var_single %>% select (- sex), na.rm = TRUE )
var_single <- var_single/ nrow (df_singlecases)* 100
var_single["sex_na" ] <- (100 - var_single["sex_m" ] - var_single["sex_f" ])
bar_df_prct <- data.frame (
x = c ("males" , "females" , "missing" , "males" , "females" , "missing" , "males" , "females" , "missing" ),
vals = c (var_single, var_cohort, var_control),
col = c (rep ("single" , length (var_single)), rep ("cohorts" , length (var_cohort)), rep ("histor ctrl" , length (var_control))
))
p_prct <- ggplot (bar_df_prct, aes (x = col, y = vals, fill = x)) +
geom_bar (stat = "identity" , position = "stack" ) +
theme_bw () +
labs (title = "Male/female distribution in dataset" , subtitle = "Prct" , x = "sex" , y = "%" , col = " " ) + lims (y = c (0 ,100 )) + theme (axis.text.x= element_text (angle= 90 , hjust= 1 ))+
scale_fill_manual (values = wes_palette ("Royal1" ))
p_prct
var_cohort <- df_cohort %>% select (contains ("sex" ) | ("cohort_id" ) | "tot_cases_n" )
sex_f <- var_cohort %>% group_by (cohort_id) %>% summarize (prct = sex_f/ tot_cases_n) %>% mutate (sex = "female" )
sex_m <- var_cohort %>% group_by (cohort_id) %>% summarize (prct = sex_m/ tot_cases_n) %>% mutate (sex = "male" )
sex_all <- rbind (sex_f, sex_m)
p_sex_cohort <- ggplot (sex_all, aes (y = cohort_id, x = prct, fill = sex)) +
geom_bar (stat = "identity" , position = "fill" ) +
theme_bw () + labs (x = "" ) +
scale_fill_manual (values = wes_palette ("Royal1" ))
var_controls <- df_cohort_controls %>% filter (cohort_id == "Pouletty - control" ) %>% select (contains ("sex" ) | ("cohort_id" ) | "tot_cases_n" )
sex_f <- var_controls %>% group_by (cohort_id) %>% summarize (prct = sex_f/ tot_cases_n) %>% mutate (sex = "female" )
sex_m <- var_controls %>% group_by (cohort_id) %>% summarize (prct = sex_m/ tot_cases_n) %>% mutate (sex = "male" )
sex_all <- rbind (sex_f, sex_m)
p_sex_controls <- ggplot (sex_all, aes (y = cohort_id, x = prct, fill = sex)) +
geom_bar (stat = "identity" , position = "fill" ) +
theme_bw () + labs (x = "" ) +
scale_fill_manual (values = wes_palette ("Royal1" ))
n_single <- df_singlecases %>% nrow ()
var_single <- df_singlecases %>% select (contains ("sex" ))
var_single$ sex_m <- ifelse (var_single$ sex == "M" , TRUE , FALSE )
var_single$ sex_f <- ifelse (var_single$ sex == "F" , TRUE , FALSE )
cols <- sapply (var_single, is.logical)
var_single[,cols] <- lapply (var_single[,cols], as.numeric)
var_single <- colSums (var_single %>% select (- sex), na.rm = TRUE )
var_single <- var_single/ nrow (df_singlecases)* 100
sex_single <- data.frame (cohort_id = "single_cases" , prct = c (var_single["sex_m" ], var_single["sex_f" ]), sex = c ("male" , "female" ))
p_sex_single <- ggplot (sex_single, aes (y = cohort_id, x = prct, fill = sex)) +
geom_bar (stat = "identity" , position = "fill" ) +
theme_bw () +
scale_fill_manual (values = wes_palette ("Royal1" ))
a <- plot_grid (p_sex_cohort, p_sex_controls, p_sex_single, align = "v" , nrow = 3 , rel_heights = c (5 / 7 , 1 / 7 , 1 / 7 ))
a
Age distribution
cohort_age <- df_cohort_controls %>% select (contains ("cohort_id" ) | contains ("age" ) | contains ("cohort_type" ) | contains ("tot_cases_n" ))
cohort_age$ cohort_id <- paste0 (cohort_age$ cohort_id, " (n = " , cohort_age$ tot_cases_n,")" )
cohort_age$ age_med_yrs <- as.numeric (cohort_age$ age_med_yrs )
cohort_age$ age_Q1_yrs <- as.numeric (cohort_age$ age_Q1_yrs)
cohort_age$ age_Q3_yrs <- as.numeric (cohort_age$ age_Q3_yrs)
cohort_age$ age_min_yrs <- as.numeric (cohort_age$ age_min_yrs)
cohort_age$ age_max_yrs <- as.numeric (cohort_age$ age_max_yrs)
cohort_age$ data_descr <- ifelse (! is.na (cohort_age$ age_Q1_yrs) & is.na (cohort_age$ age_min_yrs) , "IQR" ,
ifelse (is.na (cohort_age$ age_Q1_yrs) & ! is.na (cohort_age$ age_min_yrs), "range" ,
ifelse (! is.na (cohort_age$ age_Q1_yrs) & ! is.na (cohort_age$ age_min_yrs), "both" , "none" )))
p_age_cohort <- ggplot (cohort_age %>% filter (cohort_type == "covid" ), aes (y = cohort_id, x = age_med_yrs, col = data_descr)) +
geom_point (size = 4 ) +
geom_errorbar (aes (xmin= age_Q1_yrs, xmax= age_Q3_yrs), width= .8 , position= position_dodge (.9 )) +
geom_errorbar (aes (xmin= age_min_yrs, xmax= age_max_yrs), width= .2 , position= position_dodge (.9 )) +
theme_bw () + lims (x = c (0 ,21 )) +
labs (y = "cohort" , x = "" , col = "bars" ) + theme (legend.position= "top" )+
scale_color_manual (values = c (wes_palette ("BottleRocket2" )[1 : 3 ], wes_palette ("BottleRocket1" )[2 ]))
p_age_controls <- ggplot (cohort_age %>% filter (cohort_type != "covid" ), aes (y = cohort_id, x = age_med_yrs, col = data_descr)) +
geom_point (size = 4 ) +
geom_errorbar (aes (xmin= age_Q1_yrs, xmax= age_Q3_yrs), width= .2 , position= position_dodge (.9 )) +
geom_errorbar (aes (xmin= age_min_yrs, xmax= age_max_yrs), width= .2 , position= position_dodge (.9 )) +
theme_bw () + lims (x = c (0 ,21 )) +
labs (y = "cohort" , x = "" , col = "bars" ) + theme (legend.position= "none" )+
scale_color_manual (values = wes_palette ("BottleRocket2" )[2 ])
p_age_single <- ggplot (df_singlecases, aes (x = as.numeric (age), y = paste0 ("single cases (n = " , n_single,")" ))) +
geom_violin (fill = wes_palette ("Darjeeling2" )[4 ]) +
geom_boxplot (width= .3 , fill = wes_palette ("Darjeeling2" )[1 ]) +
theme_bw () + geom_beeswarm (groupOnX= FALSE , alpha = 0.5 ) + lims (x = c (0 ,21 )) +
labs (y = "cohort" , x = "Age (years)" )
a <- plot_grid (p_age_cohort, p_age_controls, p_age_single, align = "v" , nrow = 3 , rel_heights = c (2 / 3 , 1 / 5 , 1 / 3 ))
a
Symptoms
Single cases
All symptoms
Where applicable, overlap of variable in the single case group was summarized with Upset plots (Lex & Gehlenborg, Nature Methods, 2014) .
makeUpsetR <- function (input_df){
var_single <- input_df
cols <- sapply (var_single, is.logical)
var_single[,cols] <- lapply (var_single[,cols], as.numeric)
var_single_upsetr <- var_single
var_single_upsetr[is.na (var_single_upsetr)] <- 0
var_single_upsetr <- as.data.frame (var_single_upsetr)
for (i in 1 : ncol (var_single_upsetr)){ var_single_upsetr[ , i] <- as.integer (var_single_upsetr[ , i]) }
upset (var_single_upsetr, sets = c (colnames (var_single_upsetr)), sets.bar.color = "#56B4E9" ,
order.by = "freq" , keep.order = TRUE )#, empty.intersections = "on", keep.order = FALSE)
}
makeUpsetR (df_singlecases %>% select (contains ( "symp" )) %>% select (contains ("any" )))
Respiratory
Cardiovascular
GI
Single cases + cohort
Respiratory
barSymp <- function (colname_chort, colname_single, exclude_single = NULL , plottitle){
var_cohort <- df_cohort %>%
select (contains ("cohort_id" ) | contains ("tot_cases_n" ) | (contains (colname_chort) & contains ("_n" )))
var_cohort <- var_cohort %>%
gather (variable, value, 3 : ncol (var_cohort)) %>%
drop_na (value) %>% group_by (variable) %>%
summarize (prct = sum (value)/ sum (tot_cases_n)* 100 )
var_cohort <- setNames (var_cohort$ prct, var_cohort$ variable)
names (var_cohort) <- sub ("_n" , "" , names (var_cohort))
n_single <- df_singlecases %>% nrow ()
if (! is.null (exclude_single)){
var_single <- df_singlecases %>% select (- contains (exclude_single))
var_single <- var_single %>% select (contains (colname_single))
} else
{
var_single <- df_singlecases %>% select (contains (colname_single))
}
#%>% select(-contains("any"))
cols <- sapply (var_single, is.logical)
var_single[,cols] <- lapply (var_single[,cols], as.numeric)
var_single <- colSums (var_single, na.rm = TRUE )
var_single <- var_single/ nrow (df_singlecases)* 100
bar_df_prct <- data.frame (
x = c (names (var_single), names (var_cohort)),
vals = c (var_single, var_cohort),
col = c (rep ("single" , length (var_single)), rep ("cohorts" , length (var_cohort)))
)
p_prct <- ggplot (bar_df_prct, aes (x = x, y = vals, fill = col)) +
geom_bar (stat = "identity" , position = "dodge" ) +
theme_bw () +
labs (title = plottitle,
subtitle = "Percent of group" , x = "treatment" , y = "%" , col = " " ) +
theme (axis.text.x= element_text (angle= 90 , hjust= 1 ))+
scale_fill_manual (values = wes_palette ("Royal1" ))
p_prct
}
makeHeatmap_cohort ("symp_resp" , "symp_resp" , plottitle = "Cases with respiratory symptoms, per cohort" )
Cardiovascular
Gastro-intestinal
Kawasaki criteria
Shock
Lab values
For lab values, sometimes multiple values are reported (baseline, peak or not-specified). All lab values are collapsed based on the max (or the min for e.g. hemoglobin): so only the highest value of median, Q1 or Q3 is used. Dashed vertical line corresponds to the cutoff used in the study.
C-reactive protein
crp_collapse_cohort <- collapse_labvals_cohort (df_cohort_controls, "max" , "CRP" )
crp_collapse_single <- collapse_labvals_single (df_singlecases, "max" , "CRP" )
crp_missing <- sum (is.na (crp_collapse_single$ CRP_max))
p_crp_cohort <- ggplot (crp_collapse_cohort, aes (y = cohort_id, x = CRP_med, col = cohort_type)) +
geom_point () +
geom_errorbar (aes (xmin= CRP_min, xmax= CRP_max), width= .2 , position= position_dodge (.9 )) + lims (x = c (0 ,600 )) +
theme_bw () + labs (title = "CRP" , y = "cohort" , x = "" ) +
geom_vline (xintercept = co_CRP, linetype = "dashed" , color = "black" ) + theme (legend.justification = c (1 , 1 ), legend.position = c (0.98 , 0.98 ), legend.title= element_blank ()) +
scale_color_manual (values = wes_palette ("Royal1" ))
p_crp_single <- ggplot (crp_collapse_single, aes (x = as.numeric (CRP_max), y = cohort_id)) +
geom_violin (fill = wes_palette ("Darjeeling2" )[4 ]) +
geom_boxplot (width= .3 , fill = wes_palette ("Darjeeling2" )[1 ]) +
theme_bw () + geom_beeswarm (groupOnX= FALSE , alpha = 0.5 ) + lims (x = c (0 ,600 )) + labs (y = "" , x = "CRP (mg/dL)" , subtitle = paste0 ("missing data for " , crp_missing, " cases" )) +
geom_hline (yintercept = co_CRP, linetype = "dashed" , color = "black" )
CRP_grid <- plot_grid (p_crp_cohort, p_crp_single, align = "v" , nrow = 2 , rel_heights = c (2 / 3 , 1 / 3 ))
CRP_grid
Lymphocytes
lympho_collapse_cohort <- collapse_labvals_cohort (df_cohort_controls, "min" , "lympho" )
lympho_collapse_single <- collapse_labvals_single (df_singlecases, "min" , "lympho" )
lympho_missing <- sum (is.na (lympho_collapse_single$ lympho_min))
p_lympho_cohort <- ggplot (lympho_collapse_cohort, aes (y = cohort_id, x = lympho_med, col = cohort_type)) +
geom_point () +
geom_errorbar (aes (xmin= lympho_min, xmax= lympho_max), width= .2 , position= position_dodge (.9 )) +
theme_bw () + labs (title = "lymphocytes" , y = "" , x = "" ) + lims (x = c (0 ,7500 )) +
geom_vline (xintercept = co_lympho, linetype = "dashed" , color = "black" ) + theme (legend.justification = c (1 , 1 ), legend.position = c (0.98 , 0.98 ), legend.title= element_blank ()) +
scale_color_manual (values = wes_palette ("Royal1" ))#+
#rremove("y.text")
p_lympho_single <- ggplot (lympho_collapse_single, aes (x = as.numeric (lympho_min), y = cohort_id)) +
geom_violin (fill = wes_palette ("Darjeeling2" )[4 ]) +
geom_boxplot (width= .3 , fill = wes_palette ("Darjeeling2" )[1 ]) +
lims (x = c (0 ,7500 ))+
theme_bw () + geom_beeswarm (groupOnX= FALSE , alpha = 0.5 ) + labs (y = "" , x = "Lymphocytes (/µL)" , subtitle = paste0 ("missing data for " , lympho_missing, " cases" )) +
geom_vline (xintercept = co_lympho, linetype = "dashed" , color = "black" ) #+
#rremove("y.text")
lympho_grid <- plot_grid (p_lympho_cohort, p_lympho_single, align = "v" , nrow = 2 , rel_heights = c (2 / 3 , 1 / 3 ))
lympho_grid
White blood cells
wbc_collapse_cohort <- collapse_labvals_cohort (df_cohort_controls, "max" , "WBC" )
wbc_collapse_single <- collapse_labvals_single (df_singlecases, "max" , "WBC" )
wbc_missing <- sum (is.na (wbc_collapse_single$ WBC_max))
p_wbc_cohort <- ggplot (wbc_collapse_cohort, aes (y = cohort_id, x = WBC_med, col = cohort_type)) +
geom_point () +
geom_errorbar (aes (xmin= WBC_min, xmax= WBC_max), width= .2 , position= position_dodge (.9 )) + lims (x = c (0 ,50000 )) +
theme_bw () + labs (title = "WBC" , y = "cohort" , x = "" ) +
geom_vline (xintercept = co_WBC, linetype = "dashed" , color = "black" ) + theme (legend.justification = c (1 , 1 ), legend.position = c (0.98 , 0.98 ), legend.title= element_blank ()) +
scale_color_manual (values = wes_palette ("Royal1" ))
p_wbc_single <- ggplot (wbc_collapse_single, aes (x = as.numeric (WBC_max), y = cohort_id)) +
geom_violin (fill = wes_palette ("Darjeeling2" )[4 ]) +
geom_boxplot (width= .3 , fill = wes_palette ("Darjeeling2" )[1 ]) +
theme_bw () + geom_beeswarm (groupOnX= FALSE , alpha = 0.5 ) + labs (y = "" , x = "WBC (/µL)" , subtitle = paste0 ("missing data for " , wbc_missing, " cases" )) + lims (x = c (0 ,50000 )) +
geom_vline (xintercept = co_WBC, linetype = "dashed" , color = "black" )
WBC_grid <- plot_grid (p_wbc_cohort, p_wbc_single, align = "v" , nrow = 2 , rel_heights = c (2 / 3 , 1 / 3 ))
WBC_grid
Ferritin
ferritin_collapse_cohort <- collapse_labvals_cohort (df_cohort_controls, "max" , "ferrit" )
ferritin_collapse_single <- collapse_labvals_single (df_singlecases, "max" , "ferrit" )
ferritin_missing <- sum (is.na (ferritin_collapse_single$ ferrit_max))
p_ferritin_cohort <- ggplot (ferritin_collapse_cohort, aes (y = cohort_id, x = ferrit_med, col = cohort_type)) +
geom_point () +
geom_errorbar (aes (xmin= ferrit_min, xmax= ferrit_max), width= .2 , position= position_dodge (.9 )) + lims (x = c (0 ,11000 )) +
theme_bw () + labs (title = "Ferritin" , y = "cohort" , x = "" ) +
geom_vline (xintercept = co_ferritin, linetype = "dashed" , color = "black" ) + theme (legend.justification = c (1 , 1 ), legend.position = c (0.98 , 0.98 ), legend.title= element_blank ()) +
scale_color_manual (values = wes_palette ("Royal1" ))
p_ferritin_single <- ggplot (ferritin_collapse_single, aes (x = as.numeric (ferrit_max), y = cohort_id)) +
geom_violin (fill = wes_palette ("Darjeeling2" )[4 ]) +
geom_boxplot (width= .3 , fill = wes_palette ("Darjeeling2" )[1 ]) +
theme_bw () + geom_beeswarm (groupOnX= FALSE , alpha = 0.5 ) + labs (y = "" , x = "Ferritin (µg/l)" , subtitle = paste0 ("missing data for " , ferritin_missing, " cases" )) + lims (x = c (0 ,11000 )) +
geom_vline (xintercept = co_ferritin, linetype = "dashed" , color = "black" )
ferritin_grid <- plot_grid (p_ferritin_cohort, p_ferritin_single, align = "v" , nrow = 2 , rel_heights = c (2 / 3 , 1 / 3 ))
ferritin_grid
Troponin
troponin_collapse_cohort <- collapse_labvals_cohort (df_cohort_controls, "max" , "troponin" )
troponin_collapse_single <- collapse_labvals_single (df_singlecases, "max" , "troponin" )
troponin_missing <- sum (is.na (troponin_collapse_single$ troponin_max))
p_troponin_cohort <- ggplot (troponin_collapse_cohort, aes (y = cohort_id, x = troponin_med, col = cohort_type)) +
geom_point () +
geom_errorbar (aes (xmin= troponin_min, xmax= troponin_max), width= .2 , position= position_dodge (.9 )) + lims (x = c (0 ,7000 )) +
theme_bw () + labs (title = "Troponin" , y = "cohort" , x = "" ) +
geom_vline (xintercept = co_tropo, linetype = "dashed" , color = "black" ) + theme (legend.justification = c (1 , 1 ), legend.position = c (0.98 , 0.98 ), legend.title= element_blank ()) +
scale_color_manual (values = wes_palette ("Royal1" ))
p_troponin_single <- ggplot (troponin_collapse_single, aes (x = as.numeric (troponin_max), y = cohort_id)) +
geom_violin (fill = wes_palette ("Darjeeling2" )[4 ]) +
geom_boxplot (width= .3 , fill = wes_palette ("Darjeeling2" )[1 ]) +
theme_bw () + geom_beeswarm (groupOnX= FALSE , alpha = 0.5 ) + labs (y = "" , x = "Troponin (ng/L)" , subtitle = paste0 ("missing data for " , troponin_missing, " cases" )) + lims (x = c (0 ,7000 )) +
geom_vline (xintercept = co_tropo, linetype = "dashed" , color = "black" )
troponin_grid <- plot_grid (p_troponin_cohort, p_troponin_single, align = "v" , nrow = 2 , rel_heights = c (2 / 3 , 1 / 3 ))
troponin_grid
IL-6
Note: The cases from Pouletty et al are added to the single cases as they report on IL6 values.
IL6_collapse_cohort <- collapse_labvals_cohort (df_cohort_controls, "max" , "IL6" )
IL6_collapse_single <- collapse_labvals_single (df_singlecases_inclPouletty, "max" , "IL6" )
IL6_missing <- sum (is.na (IL6_collapse_single$ IL6_max))
p_IL6_cohort <- ggplot (IL6_collapse_cohort, aes (y = cohort_id, x = IL6_med)) +
geom_point () +
geom_errorbar (aes (xmin= IL6_min, xmax= IL6_max), width= .2 , position= position_dodge (.9 )) + lims (x = c (0 ,2500 )) +
theme_bw () + labs (title = "IL6" , y = "cohort" , x = "" ) +
geom_vline (xintercept = co_IL6, linetype = "dashed" , color = "black" ) +
scale_color_manual (values = wes_palette ("Royal1" ))
p_IL6_single <- ggplot (IL6_collapse_single, aes (x = as.numeric (IL6_max), y = cohort_id)) +
geom_violin (fill = wes_palette ("Darjeeling2" )[4 ]) +
geom_boxplot (width= .3 , fill = wes_palette ("Darjeeling2" )[1 ]) +
theme_bw () + geom_beeswarm (groupOnX= FALSE , alpha = 0.5 ) + labs (y = "" , x = "IL6 (pg/ml)" , subtitle = paste0 ("missing data for " , IL6_missing, " cases" )) + lims (x = c (0 ,2500 )) +
geom_vline (xintercept = co_IL6, linetype = "dashed" , color = "black" )
IL6_grid <- plot_grid (p_IL6_cohort, p_IL6_single, align = "v" , nrow = 2 , rel_heights = c (2 / 3 , 1 / 3 ))
IL6_grid
BNP
collapse_cohort <- collapse_labvals_cohort (df_cohort_controls, "max" , "_BNP" )
collapse_single <- collapse_labvals_single (df_singlecases, "max" , "_BNP" )
missing <- sum (is.na (collapse_single$ ` _BNP_max ` ))
p_BNP_cohort <- ggplot (collapse_cohort, aes (y = cohort_id, x = ` _BNP_med ` , col = cohort_type)) +
geom_point () +
geom_errorbar (aes (xmin= ` _BNP_min ` , xmax= ` _BNP_max ` ), width= .2 , position= position_dodge (.9 )) + lims (x = c (0 ,20000 )) +
theme_bw () + labs (title = "BNP" , y = "cohort" , x = "" ) +
geom_vline (xintercept = co_BNP, linetype = "dashed" , color = "black" ) + theme (legend.justification = c (1 , 1 ), legend.position = c (0.98 , 0.98 )) +
scale_color_manual (values = wes_palette ("Royal1" ))
p_BNP_single <- ggplot (collapse_single, aes (x = as.numeric (` _BNP_max ` ), y = cohort_id)) +
geom_violin (fill = wes_palette ("Darjeeling2" )[4 ]) +
geom_boxplot (width= .3 , fill = wes_palette ("Darjeeling2" )[1 ]) +
theme_bw () + geom_beeswarm (groupOnX= FALSE , alpha = 0.5 ) + labs (y = "" , x = "BNP (pg/ml)" , subtitle = paste0 ("missing data for " , missing, " cases" )) + lims (x = c (0 ,20000 )) +
geom_vline (xintercept = co_BNP, linetype = "dashed" , color = "black" )
BNP_grid <- plot_grid (p_BNP_cohort, p_BNP_single, align = "v" , nrow = 2 , rel_heights = c (2 / 3 , 1 / 3 ))
BNP_grid
NTproBNP
collapse_cohort <- collapse_labvals_cohort (df_cohort_controls, "max" , "NTproBNP" )
collapse_single <- collapse_labvals_single (df_singlecases, "max" , "NTproBNP" )
missing <- sum (is.na (collapse_single$ NTproBNP_max))
p_NTproBNP_cohort <- ggplot (collapse_cohort, aes (y = cohort_id, x = NTproBNP_med, col = cohort_type)) +
geom_point () +
geom_errorbar (aes (xmin= NTproBNP_min, xmax= NTproBNP_max), width= .2 , position= position_dodge (.9 )) + lims (x = c (0 ,70000 )) +
theme_bw () + labs (title = "NTproBNP" , y = "cohort" , x = "" ) +
geom_vline (xintercept = co_NTproBNP, linetype = "dashed" , color = "black" ) + theme (legend.justification = c (1 , 1 ), legend.position = c (0.98 , 0.98 ), legend.title= element_blank ()) +
scale_color_manual (values = wes_palette ("Royal1" ))
p_NTproBNP_single <- ggplot (collapse_single, aes (x = as.numeric (NTproBNP_max), y = cohort_id)) +
geom_violin (fill = wes_palette ("Darjeeling2" )[4 ]) +
geom_boxplot (width= .3 , fill = wes_palette ("Darjeeling2" )[1 ]) +
theme_bw () + geom_beeswarm (groupOnX= FALSE , alpha = 0.5 ) + labs (y = "" , x = "NTproBNP (pg/ml)" , subtitle = paste0 ("missing data for " , missing, " cases" )) + lims (x = c (0 ,70000 )) +
geom_vline (xintercept = co_NTproBNP, linetype = "dashed" , color = "black" )
NTproBNP_grid <- plot_grid (p_NTproBNP_cohort, p_NTproBNP_single, align = "v" , nrow = 2 , rel_heights = c (2 / 3 , 1 / 3 ))
NTproBNP_grid
Platelets
collapse_cohort <- collapse_labvals_cohort (df_cohort_controls, "min" , "platelet" )
collapse_single <- collapse_labvals_single (df_singlecases, "min" , "platelet" )
missing <- sum (is.na (collapse_single$ platelet_min))
p_platelet_cohort <- ggplot (collapse_cohort, aes (y = cohort_id, x = platelet_med, col = cohort_type)) +
geom_point () +
geom_errorbar (aes (xmin= platelet_min, xmax= platelet_max, col= cohort_type), width= .2 , position= position_dodge (.9 )) + lims (x = c (0 ,750000 )) +
theme_bw () + labs (title = "platelet" , y = "cohort" , x = "" ) +
geom_vline (xintercept = co_platelet, linetype = "dashed" , color = "black" ) + theme (legend.justification = c (1 , 1 ), legend.position = c (0.98 , 0.98 ), legend.title= element_blank ()) +
scale_color_manual (values = wes_palette ("Royal1" ))
p_platelet_single <- ggplot (collapse_single, aes (x = as.numeric (platelet_min), y = cohort_id)) +
geom_violin (fill = wes_palette ("Darjeeling2" )[4 ]) +
geom_boxplot (width= .3 , fill = wes_palette ("Darjeeling2" )[1 ]) +
theme_bw () + geom_beeswarm (groupOnX= FALSE , alpha = 0.5 ) + labs (y = "" , x = "Platelets (/µL)" , subtitle = paste0 ("missing data for " , missing, " cases" )) + lims (x = c (0 ,750000 )) +
geom_vline (xintercept = co_platelet, linetype = "dashed" , color = "black" )
platelet_grid <- plot_grid (p_platelet_cohort, p_platelet_single, align = "v" , nrow = 2 , rel_heights = c (2 / 3 , 1 / 3 ))
platelet_grid
D-dimers
collapse_cohort <- collapse_labvals_cohort (df_cohort_controls, "max" , "Ddim" )
collapse_single <- collapse_labvals_single (df_singlecases, "max" , "Ddim" )
missing <- sum (is.na (collapse_single$ Ddim_max))
p_Ddim_cohort <- ggplot (collapse_cohort, aes (y = cohort_id, x = Ddim_med, col = cohort_type)) +
geom_point () +
geom_errorbar (aes (xmin= Ddim_min, xmax= Ddim_max, col= cohort_type), width= .2 , position= position_dodge (.9 )) + lims (x = c (0 ,11000 )) +
theme_bw () + labs (title = "D-dimers" , y = "cohort" , x = "" ) +
geom_vline (xintercept = co_Ddim, linetype = "dashed" , color = "black" ) + theme (legend.justification = c (1 , 1 ), legend.position = c (0.98 , 0.98 ), legend.title= element_blank ()) +
scale_color_manual (values = wes_palette ("Royal1" ))
p_Ddim_single <- ggplot (collapse_single, aes (x = as.numeric (Ddim_max), y = cohort_id)) +
geom_violin (fill = wes_palette ("Darjeeling2" )[4 ]) +
geom_boxplot (width= .3 , fill = wes_palette ("Darjeeling2" )[1 ]) +
theme_bw () + geom_beeswarm (groupOnX= FALSE , alpha = 0.5 ) + labs (y = "" , x = "D-dimers (ng/ml)" , subtitle = paste0 ("missing data for " , missing, " cases" )) + lims (x = c (0 ,11000 )) +
geom_vline (xintercept = co_Ddim, linetype = "dashed" , color = "black" )
Ddim_grid <- plot_grid (p_Ddim_cohort, p_Ddim_single, align = "v" , nrow = 2 , rel_heights = c (2 / 3 , 1 / 3 ))
Ddim_grid
Sodium
collapse_cohort <- collapse_labvals_cohort (df_cohort_controls, "min" , "sodium" )
collapse_single <- collapse_labvals_single (df_singlecases, "min" , "sodium" )
missing <- sum (is.na (collapse_single$ sodium_min))
p_sodium_cohort <- ggplot (collapse_cohort, aes (y = cohort_id, x = sodium_med, col = cohort_type)) +
geom_point () +
geom_errorbar (aes (xmin= sodium_min, xmax= sodium_max, col= cohort_type), width= .2 , position= position_dodge (.9 )) + lims (x = c (100 ,200 )) +
theme_bw () + labs (title = "Sodium" , y = "cohort" , x = "" ) +
geom_vline (xintercept = co_sodium, linetype = "dashed" , color = "black" ) + theme (legend.justification = c (1 , 1 ), legend.position = c (0.98 , 0.98 ), legend.title= element_blank ()) +
scale_color_manual (values = wes_palette ("Royal1" ))
p_sodium_single <- ggplot (collapse_single, aes (x = as.numeric (sodium_min), y = cohort_id)) +
geom_violin (fill = wes_palette ("Darjeeling2" )[4 ]) +
geom_boxplot (width= .3 , fill = wes_palette ("Darjeeling2" )[1 ]) +
theme_bw () + geom_beeswarm (groupOnX= FALSE , alpha = 0.5 ) + labs (y = "" , x = "Sodium (mmol/L)" , subtitle = paste0 ("missing data for " , missing, " cases" )) + lims (x = c (100 ,200 )) +
geom_vline (xintercept = co_sodium, linetype = "dashed" , color = "black" )
sodium_grid <- plot_grid (p_sodium_cohort, p_sodium_single, align = "v" , nrow = 2 , rel_heights = c (2 / 3 , 1 / 3 ))
sodium_grid
Critical care interventions
Treatments
IVIg
Overall therapy
Case definitions
Lab reference values
Cut-offs in this study:
Neutrophilia > 8000/µL
Elevated CRP > 10 mg/L
Lymphopenia < 1250/µL
WBC > 11000/µL
Fibrinogen > 400 mg/dL
D-dimers > 250 ng/mL
Ferritin > 300 ng/mL
Albumin < 34 g/L
Procalcitonin > 0.49 ng/mL
LDH > 280 U/L
IL6 > 16.4 pg/mL
ESR > 22 mm/
BNP > 100 pg/mL
NTproBNP > 400 pg/mL
Troponin > 0.04 ng/mL
RCPCH, CDC and WHO
PIMS-TS
Source RCPCH
A child presenting with persistent fever, inflammation (neutrophilia, elevated CRP and lymphopaenia) and evidence of single or multi-organ dysfunction (shock, cardiac, respiratory, renal, gastrointestinal or neurological disorder) with additional features (see listed in Appendix 1 ). This may include children fulfilling full or partial criteria for Kawasaki disease.
Exclusion of any other microbial cause, including bacterial sepsis, staphylococcal or streptococcal shock syndromes, infections associated with myocarditis such as enterovirus (waiting for results of these investigations should not delay seeking expert advice).
SARS-CoV-2 PCR testing may be positive or negative
We are unable to evaluate criteria 2.
PIMS_TS_fulfilled <- apply (df_singlecases, 1 , function (row) {
# persistent fever, inflammation (neutrophilia, elevated CRP and lymphopaenia)
pat_id <- row["patientID_int" ]
fever <- row["symp_fever" ] == TRUE
neutrophilia <- as.numeric (row["lab_neutrophils" ]) > co_neutrophilia
elevated_CRP <- (as.numeric (row["lab_CRP_admis" ]) > co_CRP | as.numeric (row["lab_CRP_NS" ]) > co_CRP | as.numeric (row["lab_CRP_peak" ]) > co_CRP )
lymphopenia <- as.numeric (row["lab_lymphocytes_lowest" ]) < co_lympho
inflamm <- any (fever, neutrophilia, elevated_CRP, lymphopenia)
# lab values
#fibrinogen <- row["lab_fibrino"] > co_fibrino
#Ddimers <- row["lab_Ddim_peak"] > co_Ddim | row["lab_Ddim_NS"] > co_Ddim
#ferritin <- (row["lab_ferritin_NS"] > co_ferritin | row["lab_ferritin_admis"] > co_ferritin | row["lab_ferritin_peak"] > co_ferritin)
#albumin <- row["lab_albumin_admis"] < co_albu | row["lab_albumin_lowest"] < co_albu | row["lab_albumin_NS"] < co_albu
#lab_vals <- any(fibrinogen, Ddimers, ferritin, albumin)
# single or multi-organ dysfunction (shock, cardiac, respiratory, renal, gastrointestinal or neurological disorder)
pneumonia <- row["symp_resp_pneumonia" ] == TRUE
resp_failure <- row["symp_resp_failure" ] == TRUE
resp <- any (pneumonia, resp_failure)
AKI <- row["symp_renal_AKI" ] == TRUE
RRT <- row["critcare_RRT" ] == TRUE
renal <- any (AKI, RRT)
myocarditis <- row["symp_cardiovasc_myocard" ] == TRUE
pericarditis <- row["symp_cardiovasc_pericard" ] == TRUE
LVEF_under30 <- row["symp_cardiovasc_LV_less30" ] == TRUE
LVEF_30to55 <- row["symp_cardiovasc_LV_30to55" ] == TRUE
BNP <- (as.numeric (row["lab_BNP_admis" ]) > co_BNP | as.numeric (row["lab_BNP_max" ]) > co_BNP )
NTproBNP <- as.numeric (row["lab_NTproBNP" ]) > co_NTproBNP
tropo <- as.numeric (row["lab_troponin_admis" ]) > co_tropo
shock <- row["symp_cardiovasc_shock" ] == TRUE
cardiovasc <- any (myocarditis, LVEF_under30, LVEF_30to55, NTproBNP, BNP, tropo, shock)
rash <- row["kawasaki_exanthema" ] == TRUE
dermato <- any (rash)
organ_dysfunc <- sum (resp, renal, cardiovasc, dermato, na.rm = TRUE ) >= 1
criteria_fulfilled <- (inflamm) & organ_dysfunc #&lab_vals
#return(c(pat_id, "criteria1_inflamm" = inflamm, "criteria2_labvals" = lab_vals, "criteria3_organdysfunc" = organ_dysfunc, "criteria_fulfilled" = criteria_fulfilled))
return (c (pat_id, "criteria1_inflamm" = inflamm, "criteria2_organdysfunc" = organ_dysfunc, "criteria_fulfilled" = criteria_fulfilled))
})
PIMS_TS_fulfilled <- PIMS_TS_fulfilled %>% t () %>% as_tibble ()
PIMS_TS_fulfilled <- type_convert (PIMS_TS_fulfilled)
PIMS_TS_fulfilled_heatmap <- PIMS_TS_fulfilled
cols <- sapply (PIMS_TS_fulfilled_heatmap, is.logical)
PIMS_TS_fulfilled_heatmap[,cols] <- lapply (PIMS_TS_fulfilled_heatmap[,cols], as.numeric)
PIMS_TS_fulfilled_heatmap_melt <- PIMS_TS_fulfilled_heatmap %>% melt ()
PIMS_TS_fulfilled_heatmap_melt[is.na (PIMS_TS_fulfilled_heatmap_melt)] <- 2
skim (PIMS_TS_fulfilled)
Data summary
Name
PIMS_TS_fulfilled
Number of rows
95
Number of columns
4
_______________________
Column type frequency:
character
1
logical
3
________________________
Group variables
None
Variable type: character
patientID_int
0
1
9
10
0
95
0
Variable type: logical
criteria1_inflamm
0
1
1
TRU: 95
criteria2_organdysfunc
0
1
1
TRU: 95
criteria_fulfilled
0
1
1
TRU: 95
#ggplot(PIMS_TS_fulfilled_heatmap_melt, aes(x = variable, y = as.character(patientID_int), fill = as.factor(value))) + geom_tile() + theme_classic() + theme(axis.line=element_blank()) + labs(y = "Patient ID", x = "criteria", fill = "criteria met", title = "Overview of which single cases fulfill PIMS-TS case definition") + scale_fill_manual(labels = c("No", "Yes", "Missing"), values = c("pink2", "royalblue3", "darkgrey")) + theme(axis.text.x=element_text(angle=90, hjust=1))
CDC MIS-C
Source CDC and UpToDate The case definition for MIS-C is:
Age <21 years
Clinical presentation consistent with MIS-C, including all of the following:
Fever
Documented fever >38.0°C (100.4°F) for ≥24 hours or
Report of subjective fever lasting ≥24 hours
Laboratory evidence of inflammation
Severe illness requiring hospitalization
Multisystem involvement
2 or more organ systems involved
Cardiovascular (eg, shock, elevated troponin, elevated BNP, abnormal echocardiogram, arrhythmia)
Respiratory (eg, pneumonia, ARDS, pulmonary embolism)
Renal (eg, AKI, renal failure)
Neurologic (eg, seizure, stroke, aseptic meningitis)
Hematologic (eg, coagulopathy)
Gastrointestinal (eg, elevated liver enzymes, diarrhea, ileus, gastrointestinal bleeding)
Dermatologic (eg, erythroderma, mucositis, other rash)
No alternative plausible diagnoses
Recent or current SARS-CoV-2 infection or exposure
Any of the following:
Positive SARS-CoV-2 RT-PCR
Positive serology
Positive antigen test
COVID-19 exposure within the 4 weeks prior to the onset of symptoms
CDC_fulfilled <- apply (df_singlecases, 1 , function (row) {
# criteria 1
criteria1 = TRUE
# criteria 2
pat_id <- row["patientID_int" ]
# fever?
fever <- row["symp_fever" ] == TRUE | row["kawasaki_fever" ] == TRUE
inflamm <- any (fever)
# lab values evidence for inflammation
neutrophilia <- as.numeric (row["lab_neutrophils" ]) > co_neutrophilia
elevated_CRP <- (as.numeric (row["lab_CRP_admis" ]) > co_CRP | as.numeric (row["lab_CRP_NS" ]) > co_CRP | as.numeric (row["lab_CRP_peak" ]) > co_CRP )
lymphopenia <- as.numeric (row["lab_lymphocytes_lowest" ]) < co_lympho
fibrinogen <- as.numeric (row["lab_fibrino" ]) > co_fibrino
Ddimers <- as.numeric (row["lab_Ddim_peak" ]) > co_Ddim | as.numeric (row["lab_Ddim_NS" ]) > co_Ddim
ferritin <- (as.numeric (row["lab_ferritin_NS" ]) > co_ferritin | as.numeric (row["lab_ferritin_admis" ]) > co_ferritin | as.numeric (row["lab_ferritin_peak" ]) > co_ferritin)
albumin <- as.numeric (row["lab_albumin_admis" ]) < co_albu | as.numeric (row["lab_albumin_lowest" ]) < co_albu | as.numeric (row["lab_albumin_NS" ]) < co_albu
PCT <- as.numeric (row["lab_PCT_admis" ]) > co_PCT | as.numeric (row["lab_PCT_peak" ]) > co_PCT | as.numeric (row["lab_PCT_NS" ]) > co_PCT
LDH <- as.numeric (row["lab_LDH" ]) > co_LDH
IL6 <- as.numeric (row["lab_IL6" ]) > co_IL6
ESR <- as.numeric (row["lab_ESR" ]) > co_ESR
lab_vals <- any (neutrophilia, elevated_CRP, lymphopenia, fibrinogen, Ddimers, ferritin, albumin, PCT, LDH, IL6, ESR)
# Ilness requiring hospitalisation
## used surrogate parameters for hosp
hosp_ICU <- row["admis_hosp_days" ] > 1 | row["admis_ICU_days" ] > 1 | row["admis_PICU_admis" ] == TRUE
NIV <- row["critcare_NIV" ] == TRUE | row["critcare_NIV_days" ] > 1
MV <- row["critcare_MV" ] == TRUE | row["critcare_MV_days" ] > 1
inotrop <- row["critcare_inotrop" ] == TRUE | row["critcare_inotrop_days" ] > 1
ECMO <- row["critcare_ECMO" ] == TRUE
IVIg <- row["rx_IVIg_once" ] == TRUE | row["rx_IVIg_multip" ] == TRUE
biologicals <- row["rx_anakinra" ] == TRUE | row["rx_tocilizumab" ] == TRUE | row["rx_infliximab" ] == TRUE | row["rx_antibiotics" ] == TRUE | row["rx_plasma" ] == TRUE | row["rx_remdesivir" ] == TRUE
heparin <- row["rx_heparin" ] == TRUE
req_hosp <- any (hosp_ICU, NIV, MV, inotrop, ECMO, IVIg, biologicals, heparin)
## multisystem involvement >= 2
## respiratory
pneumonia <- row["symp_resp_pneumonia" ] == TRUE
resp_failure <- row["symp_resp_failure" ] == TRUE
resp <- any (pneumonia, resp_failure)
AKI <- row["symp_renal_AKI" ] == TRUE
RRT <- row["critcare_RRT" ] == TRUE
renal <- any (AKI, RRT)
myocarditis <- row["symp_cardiovasc_myocard" ] == TRUE
pericarditis <- row["symp_cardiovasc_pericard" ] == TRUE
LVEF_under30 <- row["symp_cardiovasc_LV_less30" ] == TRUE
LVEF_30to55 <- row["symp_cardiovasc_LV_30to55" ] == TRUE
BNP <- (as.numeric (row["lab_BNP_admis" ]) > co_BNP | as.numeric (row["lab_BNP_max" ]) > co_BNP )
NTproBNP <- as.numeric (row["lab_NTproBNP" ]) > co_NTproBNP
tropo <- as.numeric (row["lab_troponin_admis" ]) > co_tropo
shock <- row["symp_cardiovasc_shock" ] == TRUE
cardiovasc <- any (myocarditis, LVEF_under30, LVEF_30to55, NTproBNP, BNP, tropo, shock)
rash <- row["kawasaki_exanthema" ] == TRUE
dermato <- any (rash)
organ_dysfunc <- sum (resp, renal, cardiovasc, dermato, na.rm = TRUE ) >= 2
criteria2 <- sum (inflamm, lab_vals, req_hosp, organ_dysfunc, na.rm = TRUE ) == 4
# criteria 3
## not evaluable
criteria3 = TRUE
# criteria 4
# COVID pos?
PCR_pos <- row["covid_PCR_pos" ] == TRUE
stool_pos <- row["covid_PCR_stool_pos" ] == TRUE
closecontact <- row["covid_closecontact" ] == TRUE
IgA <- row["covid_IgA_pos" ] == TRUE
IgM <- row["covid_IgM_pos" ] == TRUE
IgG <- row["covid_IgG_pos" ] == TRUE
any_sero <- row["covid_sero_pos" ] == TRUE
criteria4 <- any (PCR_pos, stool_pos, closecontact, IgA, IgM, IgG, any_sero)
if (FALSE %in% c (criteria1, criteria2, criteria3, criteria4)){
criteria_fulfilled <- FALSE
} else if (NA %in% c (criteria1, criteria2, criteria3, criteria4)){
criteria_fulfilled <- NA
} else if (sum (criteria1, criteria2, criteria3, criteria4, na.rm = TRUE ) == 4 ){
criteria_fulfilled <- TRUE
}
#criteria_fulfilled <- sum(criteria1, criteria2, criteria3, criteria4, na.rm = TRUE) == 4
return (c (pat_id, "criteria1_age" = criteria1, "criteria2_clinical" = criteria2, "criteria3_noAlt" = criteria3, "criteria4_recentExposure" = criteria4, "criteria_fulfilled" = criteria_fulfilled))
})
CDC_fulfilled <- CDC_fulfilled %>% t () %>% as_tibble ()
CDC_fulfilled <- type_convert (CDC_fulfilled)
CDC_fulfilled_heatmap <- CDC_fulfilled
cols <- sapply (CDC_fulfilled_heatmap, is.logical)
CDC_fulfilled_heatmap[,cols] <- lapply (CDC_fulfilled_heatmap[,cols], as.numeric)
CDC_fulfilled_heatmap_melt <- CDC_fulfilled_heatmap %>% melt ()
CDC_fulfilled_heatmap_melt[is.na (CDC_fulfilled_heatmap_melt)] <- 2
skim (CDC_fulfilled)
Data summary
Name
CDC_fulfilled
Number of rows
95
Number of columns
6
_______________________
Column type frequency:
character
1
logical
5
________________________
Group variables
None
Variable type: character
patientID_int
0
1
9
10
0
95
0
Variable type: logical
criteria1_age
0
1.00
1.00
TRU: 95
criteria2_clinical
0
1.00
0.69
TRU: 66, FAL: 29
criteria3_noAlt
0
1.00
1.00
TRU: 95
criteria4_recentExposure
9
0.91
1.00
TRU: 86
criteria_fulfilled
7
0.93
0.67
TRU: 59, FAL: 29
#ggplot(CDC_fulfilled_heatmap_melt, aes(x = variable, y = as.character(patientID_int), fill = as.factor(value))) + geom_tile() + theme_classic() + theme(axis.line=element_blank()) + labs(y = "Patient ID", x = "criteria", fill = "criteria met", title = "Overview of which single cases fulfill CDC MIS-C case definition") + scale_fill_manual(labels = c("No", "Yes", "Missing"), values = c("pink2", "royalblue3", "darkgrey")) + theme(axis.text.x=element_text(angle=90, hjust=1))
WHO case definition
Source UpToDate :
All 6 criteria must be met:
Age 0 to 19 years
Fever for ≥3 days
Clinical signs of multisystem involvement (at least 2 of the following):
Rash, bilateral nonpurulent conjunctivitis, or mucocutaneous inflammation signs (oral, hands, or feet)
Hypotension or shock
Cardiac dysfunction, pericarditis, valvulitis, or coronary abnormalities (including echocardiographic findings or elevated troponin/BNP)
Evidence of coagulopathy (prolonged PT or PTT; elevated D-dimer)
Acute gastrointestinal symptoms (diarrhea, vomiting, or abdominal pain)
Elevated markers of inflammation (eg, ESR, CRP, or procalcitonin)
No other obvious microbial cause of inflammation, including bacterial sepsis and staphylococcal/streptococcal toxic shock syndromes
Evidence of SARS-CoV-2 infection
Any of the following:
Positive SARS-CoV-2 RT-PCR
Positive serology
Positive antigen test
Contact with an individual with COVID-19
#row <- df_singlecases[87, ]
WHO_fulfilled <- apply (df_singlecases, 1 , function (row) {
pat_id <- row["patientID_int" ]
# criteria 1
criteria1 = TRUE
# criteria 2: fever?
fever <- row["symp_fever" ] == TRUE | row["kawasaki_fever" ] == TRUE
criteria2 <- any (fever)
# criteria 3: clinical signs of multisystem involvement (at least 2)
## Rash, bilateral nonpurulent conjunctivitis, or mucocutaneous inflammation signs (oral, hands, or feet)
rash <- row["kawasaki_exanthema" ] == TRUE
conjunctivitis <- row["kawasaki_conjunctivitis" ] == TRUE
mucocutaneaous <- row["kawasaki_mouth" ] == TRUE | row["kawasaki_extremity" ] == TRUE
criteria3_a <- any (rash, conjunctivitis, mucocutaneaous)
## hypotension or shock
shock <- row["symp_cardiovasc_shock" ] == TRUE
criteria3_b <- any (shock)
## cardiac dysfunction
myocarditis <- row["symp_cardiovasc_myocard" ] == TRUE
pericarditis <- row["symp_cardiovasc_pericard" ] == TRUE
LVEF_under30 <- row["symp_cardiovasc_LV_less30" ] == TRUE
LVEF_30to55 <- row["symp_cardiovasc_LV_30to55" ] == TRUE
BNP <- (as.numeric (row["lab_BNP_admis" ]) > co_BNP | as.numeric (row["lab_BNP_max" ]) > co_BNP )
NTproBNP <- as.numeric (row["lab_NTproBNP" ]) > co_NTproBNP
tropo <- as.numeric (row["lab_troponin_admis" ]) > co_tropo
coronary <- row["symp_cardiovasc_cordilat" ] == TRUE | row["symp_cardiovasc_aneurysm" ] == TRUE
criteria3_c <- any (myocarditis, LVEF_under30, LVEF_30to55, NTproBNP, BNP, tropo, coronary)
## coagulopathy
fibrinogen <- as.numeric (row["lab_fibrino" ]) > co_fibrino
Ddimers <- as.numeric (row["lab_Ddim_peak" ]) > co_Ddim | as.numeric (row["lab_Ddim_NS" ]) > co_Ddim
criteria3_d <- any (fibrinogen, Ddimers)
## acute GI symptoms
GIsymp <- row["symp_GI_NS" ] == TRUE | row["symp_GI_abdopain" ] == TRUE | row["symp_GI_vomiting" ] == TRUE | row["symp_GI_diarrh" ] == TRUE | row["symp_GI_colitis" ] == TRUE
criteria3_e <- any (GIsymp)
criteria3 <- sum (criteria3_a, criteria3_b, criteria3_c, criteria3_d, criteria3_e, na.rm = TRUE ) >= 2
# criteria 4: Elevated markers of inflammation (eg, ESR, CRP, or procalcitonin)
neutrophilia <- as.numeric (row["lab_neutrophils" ]) > co_neutrophilia
elevated_CRP <- (as.numeric (row["lab_CRP_admis" ]) >= co_CRP) | (as.numeric (row["lab_CRP_NS" ]) >= co_CRP) | (as.numeric (row["lab_CRP_peak" ]) >= co_CRP )
# print(paste0(pat_id, elevated_CRP, row["lab_CRP_peak"]))
lymphopenia <- as.numeric (row["lab_lymphocytes_lowest" ]) < co_lympho
ferritin <- (as.numeric (row["lab_ferritin_NS" ]) > co_ferritin | as.numeric (row["lab_ferritin_admis" ]) > co_ferritin | as.numeric (row["lab_ferritin_peak" ]) > co_ferritin)
albumin <- as.numeric (row["lab_albumin_admis" ]) < co_albu | as.numeric (row["lab_albumin_lowest" ]) < co_albu | as.numeric (row["lab_albumin_NS" ]) < co_albu
PCT <- as.numeric (row["lab_PCT_admis" ]) > co_PCT | as.numeric (row["lab_PCT_peak" ]) > co_PCT | as.numeric (row["lab_PCT_NS" ]) > co_PCT
LDH <- as.numeric (row["lab_LDH" ]) > co_LDH
IL6 <- as.numeric (row["lab_IL6" ]) > co_IL6
ESR <- as.numeric (row["lab_ESR" ]) > co_ESR
criteria4 <- any (neutrophilia, elevated_CRP, lymphopenia, ferritin, albumin, PCT, LDH, IL6, ESR)
# criteria 5: No other obvious microbial cause of inflammation
criteria5 <- TRUE
# criteria 6: COVID pos?
PCR_pos <- row["covid_PCR_pos" ] == TRUE
stool_pos <- row["covid_PCR_stool_pos" ] == TRUE
closecontact <- row["covid_closecontact" ] == TRUE
IgA <- row["covid_IgA_pos" ] == TRUE
IgM <- row["covid_IgM_pos" ] == TRUE
IgG <- row["covid_IgG_pos" ] == TRUE
any_sero <- row["covid_sero_pos" ] == TRUE
criteria6 <- any (PCR_pos, stool_pos, closecontact, IgA, IgM, IgG, any_sero)
if (NA %in% c (criteria1, criteria2, criteria3, criteria4, criteria5, criteria6)){
criteria_fulfilled <- NA
} else if (FALSE %in% c (criteria1, criteria2, criteria3, criteria4, criteria5, criteria6)){
criteria_fulfilled <- FALSE
} else if (sum (criteria1, criteria2, criteria3, criteria4, criteria5, criteria6, na.rm = TRUE ) == 6 ){
criteria_fulfilled <- TRUE
} else {
criteria_fulfilled <- FALSE
}
return (c (pat_id, "criteria1_age" = criteria1, "criteria2_fever" = criteria2, "criteria3_clinical" = criteria3, "criteria4_inflamm" = criteria4, "criteria5_noAlt" = criteria5, "criteria6_recentExposure" = criteria6, "criteria_fulfilled" = criteria_fulfilled))
})
WHO_fulfilled <- WHO_fulfilled %>% t () %>% as_tibble ()
WHO_fulfilled <- type_convert (WHO_fulfilled)
WHO_fulfilled_heatmap <- WHO_fulfilled
cols <- sapply (WHO_fulfilled_heatmap, is.logical)
WHO_fulfilled_heatmap[,cols] <- lapply (WHO_fulfilled_heatmap[,cols], as.numeric)
WHO_fulfilled_heatmap_melt <- WHO_fulfilled_heatmap %>% melt ()
WHO_fulfilled_heatmap_melt[is.na (WHO_fulfilled_heatmap_melt)] <- 2
skim (WHO_fulfilled)
Data summary
Name
WHO_fulfilled
Number of rows
95
Number of columns
8
_______________________
Column type frequency:
character
1
logical
7
________________________
Group variables
None
Variable type: character
patientID_int
0
1
9
10
0
95
0
Variable type: logical
criteria1_age
0
1.00
1.00
TRU: 95
criteria2_fever
0
1.00
1.00
TRU: 95
criteria3_clinical
0
1.00
0.98
TRU: 93, FAL: 2
criteria4_inflamm
0
1.00
1.00
TRU: 95
criteria5_noAlt
0
1.00
1.00
TRU: 95
criteria6_recentExposure
9
0.91
1.00
TRU: 86
criteria_fulfilled
9
0.91
0.98
TRU: 84, FAL: 2
#ggplot(WHO_fulfilled_heatmap_melt, aes(x = variable, y = as.character(patientID_int), fill = as.factor(value))) + geom_tile() + theme_classic() + theme(axis.line=element_blank()) + labs(y = "Patient ID", x = "criteria", fill = "criteria met", title = "Overview of which single cases fulfill WHO MIS-C case definition") + scale_fill_manual(labels = c("No", "Yes", "Missing"), values = c("pink2", "royalblue3", "darkgrey")) + theme(axis.text.x=element_text(angle=90, hjust=1))
Per-case overview
PIMS_TS_fulfilled_heatmap_melt$ criteria <- "PIMS-TS"
WHO_fulfilled_heatmap_melt$ criteria <- "WHO"
CDC_fulfilled_heatmap_melt$ criteria <- "CDC"
full_heatmap <- rbind (PIMS_TS_fulfilled_heatmap_melt, WHO_fulfilled_heatmap_melt, CDC_fulfilled_heatmap_melt)
ggplot (full_heatmap, aes (x = variable, y = as.character (patientID_int), fill = as.factor (value))) + geom_tile () + theme_classic () + theme (axis.line= element_blank ()) + labs (y = "Patient ID" , x = "criteria" , fill = "criteria met" , title = "Overview of which single cases fulfill case definitions" ) + scale_fill_manual (labels = c ("No" , "Yes" , "Missing" ), values = wes_palette ("Zissou1" )) + theme (axis.text.x= element_text (angle= 90 , hjust= 1 )) + facet_wrap (~ criteria, scales = "free_x" )
Summary
criteria_summary <- data.frame (PIMS_TS_fulfilled %>% select (criteria_fulfilled), CDC_fulfilled %>% select (criteria_fulfilled), WHO_fulfilled %>% select (criteria_fulfilled))
colnames (criteria_summary) <- c ("PIMS-TS" , "CDC" , "WHO" )
cols <- sapply (criteria_summary, is.logical)
criteria_summary[,cols] <- lapply (criteria_summary[,cols], as.numeric)
criteria_summary <- criteria_summary %>% melt () %>%
group_by (variable) %>%
summarise (fulfilled = sum (value == 1 , na.rm = TRUE ), not_fulfilled = sum (value == 0 , na.rm = TRUE ), not_evaluable = sum (is.na (value)))
criteria_summary$ sum <- rowSums (criteria_summary[,- 1 ])
criteria_summary_melt <- criteria_summary %>% melt ()
colnames (criteria_summary_melt) <- c ("center" , "fulfilled" , "count" )
fill_bar <- ggplot (criteria_summary_melt %>% filter (fulfilled != 'sum' ), aes (x = center, y = count, fill = fulfilled)) +
geom_bar (stat = "identity" , position = "fill" ) + theme_bw () +
labs (y = "ratio" , title = "Single cases meeting which criteria" , subtitle = paste0 ("percent of total (n = " , max (criteria_summary_melt$ count) ,")" )) +
scale_fill_manual (values = wes_palette ("Royal1" )[c (1 ,2 ,4 )])
dodge_bar <- ggplot (criteria_summary_melt %>% filter (fulfilled != 'sum' ), aes (x = center, y = count, fill = fulfilled)) +
geom_bar (stat = "identity" , position = "dodge" ) + theme_bw () +
labs (y = "n" , title = "Single cases meeting which criteria" , subtitle = "absolute values" ) +
scale_fill_manual (values = wes_palette ("Royal1" )[c (1 ,2 ,4 )])
ggarrange (dodge_bar, fill_bar, legend = "bottom" , common.legend = TRUE )
Association of case definition with outcome
WHO_outcome <- WHO_fulfilled_heatmap %>% select (contains ("patientID_int" ) | contains ("criteria_fulfilled" ))
colnames (WHO_outcome) <- c ("patientID_int" , "casedef_WHO_fulfilled" )
CDC_outcome <- CDC_fulfilled_heatmap %>% select (contains ("patientID_int" ) | contains ("criteria_fulfilled" ))
colnames (CDC_outcome) <- c ("patientID_int" , "casedef_CDC_fulfilled" )
PIMS_TS_outcome <- PIMS_TS_fulfilled_heatmap %>% select (contains ("patientID_int" ) | contains ("criteria_fulfilled" ))
colnames (PIMS_TS_outcome) <- c ("patientID_int" , "casedef_PIMS_TS_fulfilled" )
assoc_outcome <- merge (WHO_outcome, CDC_outcome, by = "patientID_int" )
assoc_outcome <- merge (assoc_outcome, PIMS_TS_outcome)
#assoc_outcome <- assoc_outcome[complete.cases(assoc_outcome[ ,-1]),]
outcome_params <- df_singlecases %>% select (patientID_int | symp_cardiovasc_cordilat | symp_cardiovasc_aneurysm | symp_cardiovasc_shock | outcome_death | critcare_MV | critcare_ECMO)
assoc_outcome_full <- merge (outcome_params, assoc_outcome, by = "patientID_int" , all = TRUE )
cols <- sapply (assoc_outcome_full, is.logical)
assoc_outcome_full[,cols] <- lapply (assoc_outcome_full[,cols], as.numeric)
makeUpsetR (assoc_outcome_full %>% select (- contains ("patientID" )))
Unfavourable course
A new variable ‘unfavourable course’ made, which contains the following:
symp_cardiovasc_cordilat
symp_cardiovasc_aneurysm
symp_cardiovasc_shock
outcome_death
critcare_MV
critcare_ECMO
critcare_RRT
critcare_inotrop
admis_PICU_admis
Mild presentation means all of the above are either 0 or NA.
assoc_outcome <- merge (WHO_outcome, CDC_outcome, by = "patientID_int" )
assoc_outcome <- merge (assoc_outcome, PIMS_TS_outcome)
#assoc_outcome <- #assoc_outcome[complete.cases(assoc_outcome[ ,-1]),]
outcome_params <- df_singlecases %>% select (patientID_int | contains ("critcare" ) | contains ("admis_PICU_admis" ) | contains ("outcome_death" ) | contains ("symp_cardiovasc_cordilat" ) | contains ("symp_cardiovasc_aneurysm" ) | contains ("symp_cardiovasc_shock" ))
assoc_outcome_full <- merge (outcome_params, assoc_outcome, by = "patientID_int" )
cols <- sapply (assoc_outcome_full, is.logical)
assoc_outcome_full[,cols] <- lapply (assoc_outcome_full[,cols], as.numeric)
assoc_outcome_full$ unfavourable_course <- ifelse (assoc_outcome_full$ symp_cardiovasc_cordilat == 1 | assoc_outcome_full$ symp_cardiovasc_aneurysm == 1 | assoc_outcome_full$ symp_cardiovasc_shock == 1 | assoc_outcome_full$ outcome_death == 1 | assoc_outcome_full$ critcare_MV == 1 | assoc_outcome_full$ critcare_ECMO == 1 | assoc_outcome_full$ critcare_RRT == 1 | assoc_outcome_full$ admis_PICU_admis == 1 | assoc_outcome_full$ critcare_inotrop == 1 , 1 , 0 )
assoc_outcome_full$ mild_presentation <- ifelse ((assoc_outcome_full$ unfavourable_course == 0 | is.na (assoc_outcome_full$ unfavourable_course)), 1 , 0 )
makeUpsetR (assoc_outcome_full %>% select (contains ("casedef" ) | contains ("unfavourable_course" ) ))
PICU candidate
A new variable ‘PICU candidate’ made, which contains the following:
symp_cardiovasc_shock
outcome_death
critcare_MV
critcare_ECMO
critcare_RRT
critcare_inotrop
admis_PICU_admis
Mild presentation means all of the above are either 0 or NA.
assoc_outcome <- merge (WHO_outcome, CDC_outcome, by = "patientID_int" )
assoc_outcome <- merge (assoc_outcome, PIMS_TS_outcome)
#assoc_outcome <- assoc_outcome[complete.cases(assoc_outcome[ ,-1]),]
outcome_params <- df_singlecases %>% select (patientID_int | contains ("critcare" ) | contains ("admis_PICU_admis" ) | contains ("outcome_death" ) | contains ("symp_cardiovasc_cordilat" ) | contains ("symp_cardiovasc_aneurysm" ) | contains ("symp_cardiovasc_shock" ))
assoc_outcome_full <- merge (outcome_params, assoc_outcome, by = "patientID_int" )
cols <- sapply (assoc_outcome_full, is.logical)
assoc_outcome_full[,cols] <- lapply (assoc_outcome_full[,cols], as.numeric)
assoc_outcome_full$ PICU_candidate <- ifelse ( assoc_outcome_full$ symp_cardiovasc_shock == 1 | assoc_outcome_full$ outcome_death == 1 | assoc_outcome_full$ critcare_MV == 1 | assoc_outcome_full$ critcare_ECMO == 1 | assoc_outcome_full$ critcare_RRT == 1 | assoc_outcome_full$ admis_PICU_admis == 1 | assoc_outcome_full$ critcare_inotrop == 1 , 1 , 0 )
assoc_outcome_full$ mild_presentation <- ifelse ((assoc_outcome_full$ PICU_candidate == 0 | is.na (assoc_outcome_full$ PICU_candidate)), 1 , 0 )
makeUpsetR (assoc_outcome_full %>% select (contains ("casedef" ) | contains ("PICU_candidate" ) ))
SessionInfo
## R version 3.6.3 (2020-02-29)
## Platform: x86_64-apple-darwin15.6.0 (64-bit)
## Running under: macOS Catalina 10.15.5
##
## Matrix products: default
## BLAS: /Library/Frameworks/R.framework/Versions/3.6/Resources/lib/libRblas.0.dylib
## LAPACK: /Library/Frameworks/R.framework/Versions/3.6/Resources/lib/libRlapack.dylib
##
## locale:
## [1] en_US.UTF-8/en_US.UTF-8/en_US.UTF-8/C/en_US.UTF-8/en_US.UTF-8
##
## attached base packages:
## [1] stats graphics grDevices utils datasets methods base
##
## other attached packages:
## [1] wesanderson_0.3.6 see_0.5.1 UpSetR_1.4.0 skimr_2.1.1
## [5] psych_1.9.12.31 zoo_1.8-7 DT_0.13 naniar_0.5.2
## [9] cowplot_1.0.0 ggpubr_0.2.5 magrittr_1.5 ggbeeswarm_0.6.0
## [13] ggExtra_0.9 gridExtra_2.3 ggrepel_0.8.2 scales_1.1.1
## [17] RColorBrewer_1.1-2 broom_0.5.5 reshape2_1.4.3 httr_1.4.1
## [21] readxl_1.3.1 forcats_0.5.0 stringr_1.4.0 dplyr_0.8.5
## [25] purrr_0.3.4 readr_1.3.1 tidyr_1.0.2 tibble_3.0.1
## [29] ggplot2_3.3.1 tidyverse_1.3.0
##
## loaded via a namespace (and not attached):
## [1] nlme_3.1-144 fs_1.4.0 lubridate_1.7.4 insight_0.8.5
## [5] repr_1.1.0 tools_3.6.3 backports_1.1.7 R6_2.4.1
## [9] vipor_0.4.5 DBI_1.1.0 colorspace_1.4-1 withr_2.2.0
## [13] tidyselect_1.1.0 mnormt_1.5-6 compiler_3.6.3 cli_2.0.2
## [17] rvest_0.3.5 xml2_1.3.0 labeling_0.3 bayestestR_0.7.0
## [21] ggridges_0.5.2 digest_0.6.25 rmarkdown_2.1 base64enc_0.1-3
## [25] pkgconfig_2.0.3 htmltools_0.4.0 highr_0.8 dbplyr_1.4.2
## [29] fastmap_1.0.1 htmlwidgets_1.5.1 rlang_0.4.6 rstudioapi_0.11
## [33] shiny_1.4.0.2 farver_2.0.3 generics_0.0.2 jsonlite_1.6.1
## [37] crosstalk_1.1.0.1 parameters_0.8.0 Rcpp_1.0.4 munsell_0.5.0
## [41] fansi_0.4.1 lifecycle_0.2.0 visdat_0.5.3 stringi_1.4.6
## [45] yaml_2.2.1 plyr_1.8.6 grid_3.6.3 parallel_3.6.3
## [49] promises_1.1.0 crayon_1.3.4 miniUI_0.1.1.1 lattice_0.20-38
## [53] haven_2.2.0 hms_0.5.3 knitr_1.28 pillar_1.4.4
## [57] ggsignif_0.6.0 effectsize_0.3.1 reprex_0.3.0 glue_1.4.1
## [61] evaluate_0.14 modelr_0.1.6 vctrs_0.3.0 httpuv_1.5.2
## [65] cellranger_1.1.0 gtable_0.3.0 assertthat_0.2.1 xfun_0.12
## [69] mime_0.9 xtable_1.8-4 later_1.0.0 beeswarm_0.2.3
## [73] ellipsis_0.3.1
LS0tCnRpdGxlOiAiTXVsdGlzeXN0ZW0gaW5mbGFtbWF0b3J5IHN5bmRyb21lIGluIGNoaWxkcmVuIHJlbGF0ZWQgdG8gQ09WSUQtMTk6IGEgc3lzdGVtYXRpYyByZXZpZXciCnN1YnRpdGxlOiAiRXh0ZW5kZWQgbWV0aG9kcyBhbmQgZGF0YSBhbmFseXNpcyIKYXV0aG9yOiAiTGV2aSBIb3N0ZSwgUnViZW4gVmFuIFBhZW1lbCosIEZpbG9tZWVuIEhhZXJ5bmNrIgpkYXRlOiAiYHIgZm9ybWF0KFN5cy50aW1lKCksICclZCAlQiwgJVksICVIOiVNOiVTJylgIgpvdXRwdXQ6CiAgaHRtbF9kb2N1bWVudDoKICAgIGNvZGVfZm9sZGluZzogaGlkZQogICAgaGlnaGxpZ2h0OiBrYXRlCiAgICBudW1iZXJfc2VjdGlvbnM6IHllcwogICAgdGhlbWU6IGNvc21vCiAgICB0b2M6IHllcwogICAgdG9jX2Zsb2F0OiB5ZXMKICAgIGRmX3ByaW50OiBwYWdlZAogICAgY29kZV9kb3dubG9hZDogdHJ1ZQogICAgZmlnX2NhcHRpb246IHllcwotLS0KCjxzdHlsZT4KYm9keSB7CnRleHQtYWxpZ246IGp1c3RpZnl9Cjwvc3R5bGU+CgoKIyBJbnRyb2R1Y3Rpb24KSW4gdGhpcyBSTWFya2Rvd24gZmlsZSwgdGhlIGV4dGVuZGVkIG1ldGhvZHMgYW5kIGRhdGEtYW5hbHlzaXMgZm9yIHRoZSBtYW51c2NyaXB0ICJNdWx0aXN5c3RlbSBpbmZsYW1tYXRvcnkgc3luZHJvbWUgaW4gY2hpbGRyZW4gcmVsYXRlZCB0byBDT1ZJRC0xOTogYSBzeXN0ZW1hdGljIHJldmlldyIgaXMgZGVzY3JpYmVkLiBUaGUgY29tcGxldGUgZGF0YS1hbmFseXNpcyBjYW4gYmUgcmVwcm9kdWNlZCBmcm9tIHRoZSBkYXRhIGNvbGxlY3Rpb24gc2hlZXQgKGluIC54bHMgZm9ybWF0KSwgcHJvdmlkZWQgaW4gdGhlIHN1cHBsZW1lbnRhcnkgZmlsZXMgb2YgdGhlIG1hbnVzY3JpcHQgb3Igb24gW0dpdGh1Yl0oaHR0cHM6Ly9naXRodWIuY29tL3JtdnBhZW1lL1BJTVNfVFMpLgoKUHJpb3IgdG8gY29uZHVjdGluZyB0aGXigK9yZXZpZXcsIHRoZeKAr3N0dWR54oCvcHJvdG9jb2zigK93YXMgcHVibGlzaGVkIG9uIHRoZeKAr1tQUk9TUEVST+KAr3N5c3RlbWF0aWMgcmV2aWV34oCvcmVnaXN0ZXLigK8oQ1JENDIwMjAxODkyNDgpXShodHRwczovL3d3dy5jcmQueW9yay5hYy51ay9wcm9zcGVyby9kaXNwbGF5X3JlY29yZC5waHA/UmVjb3JkSUQ9MTg5MjQ4KS4KCmBgYHtyIHNldHVwLCBpbmNsdWRlPVRSVUUsIHdhcm5pbmcgPSBGQUxTRSwgbWVzc2FnZSA9IEZBTFNFfQprbml0cjo6b3B0c19jaHVuayRzZXQoY2FjaGUgPSBGQUxTRSwgd2FybmluZyA9IEZBTFNFLCBtZXNzYWdlID0gRkFMU0UpCm9wdGlvbnMoZGlnaXRzID0gMykKbGlicmFyeSh0aWR5dmVyc2UpCnJlcXVpcmUocmVhZHhsKQpyZXF1aXJlKGh0dHIpCnJlcXVpcmUocmVzaGFwZTIpCnJlcXVpcmUoYnJvb20pCnJlcXVpcmUoUkNvbG9yQnJld2VyKQpyZXF1aXJlKHNjYWxlcykKcmVxdWlyZShnZ3JlcGVsKQpyZXF1aXJlKGdyaWRFeHRyYSkKcmVxdWlyZShnZ0V4dHJhKQpsaWJyYXJ5KGdnYmVlc3dhcm0pCnJlcXVpcmUoZ2dwdWJyKQpsaWJyYXJ5KGNvd3Bsb3QpCmxpYnJhcnkobmFuaWFyKQpyZXF1aXJlKERUKQpyZXF1aXJlKHpvbykKcmVxdWlyZShwc3ljaCkKbGlicmFyeShza2ltcikKbGlicmFyeShVcFNldFIpCmxpYnJhcnkoc2VlKQpsaWJyYXJ5KHdlc2FuZGVyc29uKQoKb3B0aW9ucyhzY2lwZW49OTk5KQoKY29faGIgPC0gMTIKY29fbmV1dHJvcGhpbGlhIDwtIDgwMDAKY29fQ1JQIDwtIDEwCmNvX2x5bXBobyA8LSAxMjUwCmNvX2ZpYnJpbm8gPC0gNDAwCmNvX0RkaW0gPC0gMjUwCmNvX2ZlcnJpdGluIDwtIDMwMApjb19hbGJ1IDwtIDM0CmNvX1BDVCA8LSAwLjQ5CmNvX0xESCA8LSAyODAKY29fSUw2IDwtIDE2LjQKY29fRVNSIDwtIDIyCmNvX0JOUCA8LSAxMDAKY29fTlRwcm9CTlAgPC0gNDAwCmNvX3Ryb3BvIDwtIDQwCmNvX1dCQyA8LSAxMTAwMApjb19wbGF0ZWxldCA8LSAxNTAwMDAKY29fc29kaXVtIDwtIDEzNQojaW5wdXQgPSBkZl9jb2hvcnRfY29udHJvbHMKI2ZpbmQgPSAibWF4IgojcGFyYW0gPSAiQ1JQIgoKY29sbGFwc2VfbGFidmFsc19jb2hvcnQgPC0gZnVuY3Rpb24oaW5wdXQsIGZpbmQsIHBhcmFtLCB2ZXJib3NlID0gRkFMU0UpewogIGlmIChmaW5kID09ICJtYXgiKXsKICAgIGRmIDwtIGlucHV0ICU+JSBzZWxlY3QoY29udGFpbnMocGFyYW0pIHwgY29udGFpbnMoImNvaG9ydF9pZCIpIHwgY29udGFpbnMoImNvaG9ydF90eXBlIikgfCBjb250YWlucygidG90X2Nhc2VzX24iKSkKICAgIGlmICh2ZXJib3NlID09IFRSVUUpewogICAgICBwcmludCgiQ29sdW1uIGV4dHJhY3RlZCBmcm9tIGNvaG9ydHM6IikKICAgICAgcHJpbnQoY29sbmFtZXMoZGYpKQogICAgfQogICAgZGZfbWVkIDwtIGRmICU+JSBzZWxlY3QoY29udGFpbnMoIm1lZCIpKQogICAgZGZfbWVkIDwtIHR5cGVfY29udmVydChkZl9tZWQpCiAgICBkZl9tZWQgPC0gZGZfbWVkICU+JSBtdXRhdGVfYWxsKGZ1bnMocmVwbGFjZV9uYSguLCAtOTk5KSkpCiAgICMgY29sbmFtZXMoZGZfbWVkKVttYXguY29sKGRmX21lZCx0aWVzLm1ldGhvZD0iZmlyc3QiKV0KICAgIGRmX21lZCA8LSBkZl9tZWQgJT4lIG11dGF0ZShtZWQgPSBhcy5udW1lcmljKGFwcGx5KGRmX21lZCwgMSwgbWF4KSkpCiAgICAKICAgIGRmX21pbiA8LSBkZiAlPiUgc2VsZWN0KGNvbnRhaW5zKCJRMSIpKQogICAgZGZfbWluIDwtIHR5cGVfY29udmVydChkZl9taW4pCiAgICBkZl9taW4gPC0gZGZfbWluICU+JSBtdXRhdGVfYWxsKGZ1bnMocmVwbGFjZV9uYSguLCAwKSkpCiAgICAjY29sbmFtZXMoZGZfbWluKVttYXguY29sKGRmX21pbix0aWVzLm1ldGhvZD0iZmlyc3QiKV0KICAgIGRmX21pbiA8LSBkZl9taW4gJT4lIG11dGF0ZShtaW4gPSBhcy5udW1lcmljKGFwcGx5KGRmX21pbiwgMSwgbWF4KSkpCiAgICAKICAgIGRmX21heCA8LSBkZiAlPiUgc2VsZWN0KGNvbnRhaW5zKCJRMyIpKQogICAgZGZfbWF4IDwtIHR5cGVfY29udmVydChkZl9tYXgpCiAgICBkZl9tYXggPC0gZGZfbWF4ICU+JSBtdXRhdGVfYWxsKGZ1bnMocmVwbGFjZV9uYSguLCAwKSkpCiAgICAjY29sbmFtZXMoZGZfbWF4KVttYXguY29sKGRmX21heCx0aWVzLm1ldGhvZD0iZmlyc3QiKV0KICAgIGRmX21heCA8LSBkZl9tYXggJT4lIG11dGF0ZShtYXggPSBhcy5udW1lcmljKGFwcGx5KGRmX21heCwgMSwgbWF4KSkpCiAgICAKICAgIGRmX2Z1bGwgPC0gY2JpbmQoZGYgJT4lIHNlbGVjdChjb2hvcnRfaWQsIGNvaG9ydF90eXBlLCB0b3RfY2FzZXNfbiksIGRmX21lZCAlPiUgc2VsZWN0KG1lZCksIGRmX21pbiAlPiUgc2VsZWN0KG1pbiksIGRmX21heCAlPiUgc2VsZWN0KG1heCkpCiAgICBkZl9mdWxsW2RmX2Z1bGwgPT0gLTk5OV0gPC0gTkEKICAgIG5hbWVzKGRmX2Z1bGwpW25hbWVzKGRmX2Z1bGwpID09ICdtYXgnXSA8LSBwYXN0ZTAocGFyYW0sICJfbWF4IikKICAgIG5hbWVzKGRmX2Z1bGwpW25hbWVzKGRmX2Z1bGwpID09ICdtaW4nXSA8LSBwYXN0ZTAocGFyYW0sICJfbWluIikKICAgIG5hbWVzKGRmX2Z1bGwpW25hbWVzKGRmX2Z1bGwpID09ICdtZWQnXSA8LSBwYXN0ZTAocGFyYW0sICJfbWVkIikKICAgIGRmX2Z1bGwkZGF0YV9kZXNjciA8LSAiSVFSIgogICAgZGZfZnVsbCRjb2hvcnRfaWQgPC0gcGFzdGUwKGRmX2Z1bGwkY29ob3J0X2lkLCAiIChuID0gIiwgYXMuY2hhcmFjdGVyKGRmX2Z1bGwkdG90X2Nhc2VzX24pLCIpIikKICAgIHdyaXRlLmNzdihkZl9mdWxsLCBwYXN0ZTAoIi4vZGF0YS9jb2hvcnRfIiwgcGFyYW0sICIuY3N2IikpCiAgICBwcmludChkYXRhdGFibGUoZGZfZnVsbCwgY2FwdGlvbiA9IHBhc3RlMCgib3ZlcnZpZXcgb2YgIiwgcGFyYW0pKSkKICAgIHJldHVybihkZl9mdWxsKQogIH0KICAgIGVsc2UgaWYgKGZpbmQgPT0gIm1pbiIpewogICAgZGYgPC0gaW5wdXQgJT4lIHNlbGVjdChjb250YWlucyhwYXJhbSkgfCBjb250YWlucygiY29ob3J0X2lkIikgfCBjb250YWlucygiY29ob3J0X3R5cGUiKSB8IGNvbnRhaW5zKCJ0b3RfY2FzZXNfbiIpKQogICAgaWYgKHZlcmJvc2UgPT0gVFJVRSl7CiAgICBwcmludCgiQ29sdW1uIGV4dHJhY3RlZCBmcm9tIGNvaG9ydHM6IikKICAgIHByaW50KGNvbG5hbWVzKGRmKSkKICAgIH0KICAgIGRmX21lZCA8LSBkZiAlPiUgc2VsZWN0KGNvbnRhaW5zKCJtZWQiKSkKICAgIGRmX21lZCA8LSB0eXBlX2NvbnZlcnQoZGZfbWVkKQogICAgZGZfbWVkIDwtIGRmX21lZCAlPiUgbXV0YXRlX2FsbChmdW5zKHJlcGxhY2VfbmEoLiwgMWU2KSkpCiAgICMgY29sbmFtZXMoZGZfbWVkKVttYXguY29sKGRmX21lZCx0aWVzLm1ldGhvZD0iZmlyc3QiKV0KICAgIGRmX21lZCA8LSBkZl9tZWQgJT4lIG11dGF0ZShtZWQgPSBhcy5udW1lcmljKGFwcGx5KGRmX21lZCwgMSwgbWluKSkpCiAgICAKICAgIGRmX21pbiA8LSBkZiAlPiUgc2VsZWN0KGNvbnRhaW5zKCJRMSIpKQogICAgZGZfbWluIDwtIHR5cGVfY29udmVydChkZl9taW4pCiAgICBkZl9taW4gPC0gZGZfbWluICU+JSBtdXRhdGVfYWxsKGZ1bnMocmVwbGFjZV9uYSguLCAxZTYpKSkKICAgICNjb2xuYW1lcyhkZl9taW4pW21heC5jb2woZGZfbWluLHRpZXMubWV0aG9kPSJmaXJzdCIpXQogICAgZGZfbWluIDwtIGRmX21pbiAlPiUgbXV0YXRlKG1pbiA9IGFzLm51bWVyaWMoYXBwbHkoZGZfbWluLCAxLCBtaW4pKSkKICAgIAogICAgZGZfbWF4IDwtIGRmICU+JSBzZWxlY3QoY29udGFpbnMoIlEzIikpCiAgICBkZl9tYXggPC0gdHlwZV9jb252ZXJ0KGRmX21heCkKICAgIGRmX21heCA8LSBkZl9tYXggJT4lIG11dGF0ZV9hbGwoZnVucyhyZXBsYWNlX25hKC4sIDFlNikpKQogICAgI2NvbG5hbWVzKGRmX21heClbbWF4LmNvbChkZl9tYXgsdGllcy5tZXRob2Q9ImZpcnN0IildCiAgICBkZl9tYXggPC0gZGZfbWF4ICU+JSBtdXRhdGUobWF4ID0gYXMubnVtZXJpYyhhcHBseShkZl9tYXgsIDEsIG1pbikpKQogICAgCiAgICBkZl9mdWxsIDwtIGNiaW5kKGRmICU+JSBzZWxlY3QoY29ob3J0X2lkLCBjb2hvcnRfdHlwZSwgdG90X2Nhc2VzX24pLCBkZl9tZWQgJT4lIHNlbGVjdChtZWQpLCBkZl9taW4gJT4lIHNlbGVjdChtaW4pLCBkZl9tYXggJT4lIHNlbGVjdChtYXgpKQogICAgZGZfZnVsbFtkZl9mdWxsID09IDFlNl0gPC0gTkEKICAgIG5hbWVzKGRmX2Z1bGwpW25hbWVzKGRmX2Z1bGwpID09ICdtYXgnXSA8LSBwYXN0ZTAocGFyYW0sICJfbWF4IikKICAgIG5hbWVzKGRmX2Z1bGwpW25hbWVzKGRmX2Z1bGwpID09ICdtaW4nXSA8LSBwYXN0ZTAocGFyYW0sICJfbWluIikKICAgIG5hbWVzKGRmX2Z1bGwpW25hbWVzKGRmX2Z1bGwpID09ICdtZWQnXSA8LSBwYXN0ZTAocGFyYW0sICJfbWVkIikKICAgIGRmX2Z1bGwkZGF0YV9kZXNjciA8LSAiSVFSIgogICAgZGZfZnVsbCRjb2hvcnRfaWQgPC0gcGFzdGUwKGRmX2Z1bGwkY29ob3J0X2lkLCAiIChuID0gIiwgYXMuY2hhcmFjdGVyKGRmX2Z1bGwkdG90X2Nhc2VzX24pLCIpIikKICAgIHdyaXRlLmNzdihkZl9mdWxsLCBwYXN0ZTAoIi4vZGF0YS9jb2hvcnRfIiwgcGFyYW0sICIuY3N2IikpCiAgICBwcmludChkYXRhdGFibGUoZGZfZnVsbCwgY2FwdGlvbiA9IHBhc3RlMCgib3ZlcnZpZXcgb2YgIiwgcGFyYW0pKSkKICAgIHJldHVybihkZl9mdWxsKQogIH0KfQoKI2lucHV0ID0gZGZfc2luZ2xlY2FzZXMKI2ZpbmQgPSAibWF4IgojcGFyYW0gPSAiQ1JQIgoKY29sbGFwc2VfbGFidmFsc19zaW5nbGUgPC0gZnVuY3Rpb24oaW5wdXQsIGZpbmQsIHBhcmFtLCB2ZXJib3NlID0gRkFMU0UpewogIGlmIChmaW5kID09ICJtYXgiKXsKICAgIGRmIDwtIGlucHV0ICU+JSBzZWxlY3QoY29udGFpbnMocGFyYW0pIHwgY29udGFpbnMoImNvaG9ydF9pZCIpKQogICAgaWYgKHZlcmJvc2UgPT0gVFJVRSl7CiAgICBwcmludCgiQ29sdW1uIGV4dHJhY3RlZCBmcm9tIHNpbmdsZSBjYXNlczoiKQogICAgcHJpbnQoY29sbmFtZXMoZGYpKQogICAgfQogICAgZGZfY29sbCA8LSBkZiAlPiUgbXV0YXRlX2FsbChmdW5zKHJlcGxhY2VfbmEoLiwgLTk5OSkpKQogICAgZGZfY29sbCA8LSB0eXBlX2NvbnZlcnQoZGZfY29sbCkKICAgIyBjb2xuYW1lcyhkZl9tZWQpW21heC5jb2woZGZfbWVkLHRpZXMubWV0aG9kPSJmaXJzdCIpXQogICAgZGZfY29sbCA8LSBkZl9jb2xsICU+JSBtdXRhdGUobWF4ID0gYXMubnVtZXJpYyhhcHBseShkZl9jb2xsLCAxLCBtYXgpKSkKICAgIAogICAgZGZfY29sbFtkZl9jb2xsID09IC05OTldIDwtIE5BCiAgICBuYW1lcyhkZl9jb2xsKVtuYW1lcyhkZl9jb2xsKSA9PSAnbWF4J10gPC0gcGFzdGUwKHBhcmFtLCAiX21heCIpCiAgICBkZl9jb2xsJGRhdGFfZGVzY3IgPC0gIklRUiIKICAgIGRmX2NvbGwkY29ob3J0X2lkIDwtIHBhc3RlMCgic2luZ2xlIGNhc2VzIChuID0gIiwgYXMuY2hhcmFjdGVyKG5fc2luZ2xlX2Nhc2VzKSwiKSIpCiAgICB3cml0ZS5jc3Yoc2tpbShkZl9jb2xsKSwgcGFzdGUwKCIuL2RhdGEvc2luZ2xlY2FzZXNfIiwgcGFyYW0sICIuY3N2IikpCiAgICByZXR1cm4oZGZfY29sbCkKICB9CiAgICBlbHNlIGlmIChmaW5kID09ICJtaW4iKXsKICAgIGRmIDwtIGlucHV0ICU+JSBzZWxlY3QoY29udGFpbnMocGFyYW0pIHwgY29udGFpbnMoImNvaG9ydF9pZCIpKQogICAgaWYgKHZlcmJvc2UgPT0gVFJVRSl7CiAgICBwcmludCgiQ29sdW1uIGV4dHJhY3RlZCBmcm9tIHNpbmdsZSBjYXNlczoiKQogICAgcHJpbnQoY29sbmFtZXMoZGYpKQogICAgfQogICAgZGZfY29sbCA8LSBkZiAlPiUgbXV0YXRlX2FsbChmdW5zKHJlcGxhY2VfbmEoLiwgMWU2KSkpCiAgICMgY29sbmFtZXMoZGZfbWVkKVttYXguY29sKGRmX21lZCx0aWVzLm1ldGhvZD0iZmlyc3QiKV0KICAgIGRmX2NvbGwgPC0gZGZfY29sbCAlPiUgbXV0YXRlKG1pbiA9IGFzLm51bWVyaWMoYXBwbHkoZGZfY29sbCwgMSwgbWluKSkpCiAgICAKICAgIGRmX2NvbGxbZGZfY29sbCA9PSAxZTZdIDwtIE5BCiAgICBuYW1lcyhkZl9jb2xsKVtuYW1lcyhkZl9jb2xsKSA9PSAnbWluJ10gPC0gcGFzdGUwKHBhcmFtLCAiX21pbiIpCiAgICBkZl9jb2xsJGNvaG9ydF9pZCA8LSBwYXN0ZTAoInNpbmdsZSBjYXNlcyAobiA9ICIsIGFzLmNoYXJhY3RlcihuX3NpbmdsZV9jYXNlcyksIikiKQogICAgd3JpdGUuY3N2KHNraW0oZGZfY29sbCksIHBhc3RlMCgiLi9kYXRhL3NpbmdsZWNhc2VzXyIsIHBhcmFtLCAiLmNzdiIpKQogICAgcmV0dXJuKGRmX2NvbGwpCiAgfQp9CgoKbW92ZW1lIDwtIGZ1bmN0aW9uIChkZiwgbW92ZWNvbW1hbmQpIHsKICBpbnZlYyA8LSBuYW1lcyhkZikKICAKICBtb3ZlY29tbWFuZCA8LSBsYXBwbHkoc3Ryc3BsaXQoc3Ryc3BsaXQobW92ZWNvbW1hbmQsICI7IilbWzFdXSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICIsfFxccysiKSwgZnVuY3Rpb24oeCkgeFt4ICE9ICIiXSkKICBtb3ZlbGlzdCA8LSBsYXBwbHkobW92ZWNvbW1hbmQsIGZ1bmN0aW9uKHgpIHsKICAgIFdoZXJlIDwtIHhbd2hpY2goeCAlaW4lIGMoImJlZm9yZSIsICJhZnRlciIsICJmaXJzdCIsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAibGFzdCIpKTpsZW5ndGgoeCldCiAgICBUb01vdmUgPC0gc2V0ZGlmZih4LCBXaGVyZSkKICAgIGxpc3QoVG9Nb3ZlLCBXaGVyZSkKICB9KQogIG15VmVjIDwtIGludmVjCiAgZm9yIChpIGluIHNlcV9hbG9uZyhtb3ZlbGlzdCkpIHsKICAgIHRlbXAgPC0gc2V0ZGlmZihteVZlYywgbW92ZWxpc3RbW2ldXVtbMV1dKQogICAgQSA8LSBtb3ZlbGlzdFtbaV1dW1syXV1bMV0KICAgIGlmIChBICVpbiUgYygiYmVmb3JlIiwgImFmdGVyIikpIHsKICAgICAgYmEgPC0gbW92ZWxpc3RbW2ldXVtbMl1dWzJdCiAgICAgIGlmIChBID09ICJiZWZvcmUiKSB7CiAgICAgICAgYWZ0ZXIgPC0gbWF0Y2goYmEsIHRlbXApIC0gMQogICAgICB9CiAgICAgIGVsc2UgaWYgKEEgPT0gImFmdGVyIikgewogICAgICAgIGFmdGVyIDwtIG1hdGNoKGJhLCB0ZW1wKQogICAgICB9CiAgICB9CiAgICBlbHNlIGlmIChBID09ICJmaXJzdCIpIHsKICAgICAgYWZ0ZXIgPC0gMAogICAgfQogICAgZWxzZSBpZiAoQSA9PSAibGFzdCIpIHsKICAgICAgYWZ0ZXIgPC0gbGVuZ3RoKG15VmVjKQogICAgfQogICAgbXlWZWMgPC0gYXBwZW5kKHRlbXAsIHZhbHVlcyA9IG1vdmVsaXN0W1tpXV1bWzFdXSwgYWZ0ZXIgPSBhZnRlcikKICB9CiAgCiAgZGZbLG1hdGNoKG15VmVjLCBuYW1lcyhkZikpXQp9CgptYWtlQmFycGxvdCA8LSBmdW5jdGlvbih2YXJfaWRfY29ob3J0LCB2YXJfaWRfc2luZ2xlLCB2YXJfaWQpewoKICAgICAgICBuX2NvaG9ydCA8LSBkZl9jb2hvcnQgJT4lIHNlbGVjdCh0b3RfY2FzZXNfbikgJT4lIHN1bSgpIywgb3V0Y29tZV9kZWF0aF9uKQogICAgICAgIHZhcl9jb2hvcnQgPC0gZGZfY29ob3J0W3Zhcl9pZF9jb2hvcnRdICU+JSBzdW0oLiwgbmEucm0gPSBUUlVFKSMsIG91dGNvbWVfZGVhdGhfbikKICAgICAgICAKICAgICAgICBuX3NpbmdsZSA8LSBkZl9zaW5nbGVjYXNlcyAlPiUgbnJvdygpCiAgICAgICAgCiAgICAgICAgdmFyX3NpbmdsZSA8LSBkZl9zaW5nbGVjYXNlcyAlPiUgZmlsdGVyKGdldCh2YXJfaWRfc2luZ2xlKSA9PSBUUlVFKSAlPiUgbnJvdygpCiAgICAgICAgCiAgICAgICAgbl9hbGwgPC0gbl9jb2hvcnQgKyBuX3NpbmdsZQogICAgICAgIHZhcl9hbGwgPC0gdmFyX2NvaG9ydCArIHZhcl9zaW5nbGUKICAgICAgICAKICAgICAgICBiYXJfZGZfYWJzIDwtIGRhdGEuZnJhbWUoeCA9IGMoImNvaG9ydCIsICJjb2hvcnQiLCAic2luZ2xlIGNhc2VzIiwgInNpbmdsZSBjYXNlcyIsICJhbGwiLCAiYWxsIiksIGNvbCA9IGMoInRvdGFsIiwgdmFyX2lkLCAidG90YWwiLCB2YXJfaWQsICJ0b3RhbCIsIHZhcl9pZCksIHZhbHMgPSBjKG5fY29ob3J0LCB2YXJfY29ob3J0LCBuX3NpbmdsZSwgdmFyX3NpbmdsZSwgbl9hbGwsIHZhcl9hbGwpICkKICAgICAgICAKICAgICAgICBiYXJfZGZfcHJjdCA8LSBkYXRhLmZyYW1lKHggPSBjKCJjb2hvcnQiLCAiY29ob3J0IiwgInNpbmdsZSBjYXNlcyIsICJzaW5nbGUgY2FzZXMiLCAiYWxsIiwgImFsbCIpLCBjb2wgPSBjKHBhc3RlMCh2YXJfaWQsICIgLSIpLCBwYXN0ZTAodmFyX2lkLCAiICsiKSwgcGFzdGUwKHZhcl9pZCwgIiAtIiksIHBhc3RlMCh2YXJfaWQsICIgKyIpLCBwYXN0ZTAodmFyX2lkLCAiIC0iKSwgcGFzdGUwKHZhcl9pZCwgIiArIikpLCB2YWxzID0gYygxMDAtKHZhcl9jb2hvcnQvbl9jb2hvcnQqMTAwKSwgdmFyX2NvaG9ydC9uX2NvaG9ydCoxMDAsIDEwMC0odmFyX3NpbmdsZS9uX3NpbmdsZSoxMDApLCB2YXJfc2luZ2xlL25fc2luZ2xlKjEwMCwgMTAwLSh2YXJfYWxsL25fYWxsKjEwMCksIHZhcl9hbGwvbl9hbGwqMTAwKSApCgogICAgICAgIAogICAgICAgIHBfYWJzIDwtIGdncGxvdChiYXJfZGZfYWJzLCBhZXMoeCA9IHgsIHkgPSAgdmFscywgZmlsbCA9IGNvbCkpICsKICAgICAgICAgICAgZ2VvbV9iYXIoc3RhdCA9ICJpZGVudGl0eSIsIHBvc2l0aW9uID0gImRvZGdlIikgKwogICAgICAgICAgICB0aGVtZV9idygpICsgCiAgICAgICAgICAgIGxhYnModGl0bGUgPSBwYXN0ZTAoIlRvdGFsIGNhc2VzIHZzICIsIHZhcl9pZCksIHN1YnRpdGxlID0gIkFic29sdXRlIG51bWJlcnMiLCB4ID0gImdyb3VwIiwgeSA9ICJuIiwgY29sID0gIiIpICsKICBzY2FsZV9maWxsX21hbnVhbCh2YWx1ZXMgPSB3ZXNfcGFsZXR0ZSgiUm95YWwxIikpCiAgICAgICAgCiAgICAgICAgCiAgICAgICAgcF9wcmN0IDwtIGdncGxvdChiYXJfZGZfcHJjdCwgYWVzKHggPSB4LCB5ID0gIHZhbHMsIGZpbGwgPSBjb2wpKSArCiAgICAgICAgICAgIGdlb21fYmFyKHN0YXQgPSAiaWRlbnRpdHkiLCBwb3NpdGlvbiA9ICJmaWxsIikgKwogICAgICAgICAgICB0aGVtZV9idygpICsgCiAgICAgICAgICAgIGxhYnModGl0bGUgPSBwYXN0ZTAodmFyX2lkKSwgc3VidGl0bGUgPSAiUGVyY2VudCIsIHggPSAiZ3JvdXAiLCB5ID0gIiUiLCBjb2wgPSAiIikgICsKICAgIHNjYWxlX3lfY29udGludW91cyhsYWJlbHMgPSBzY2FsZXM6OnBlcmNlbnQpKwogIHNjYWxlX2ZpbGxfbWFudWFsKHZhbHVlcyA9IHdlc19wYWxldHRlKCJSb3lhbDEiKSkKICAgICAgICAKICAgICAgICBnZ2FycmFuZ2UocF9hYnMsIHBfcHJjdCwgbGVnZW5kID0gImJvdHRvbSIpCiAgCn0KCm1ha2VIZWF0bWFwX2NvaG9ydCA8LSBmdW5jdGlvbihwYXJhbTEsIGNvbG5hbWVfc2luZ2xlLCBleGNsdWRlX3NpbmdsZSA9IE5VTEwsIHBsb3R0aXRsZSwgdGV4dHNpemUgPSAzKXsKICB2YXJfY29ob3J0IDwtIGRmX2NvaG9ydCAlPiUgc2VsZWN0KCgiY29ob3J0X2lkIikgfCAidG90X2Nhc2VzX24iIHwgKCBjb250YWlucyhwYXJhbTEpICYgY29udGFpbnMoIl9uIikpKQogIHZhcl9jb2hvcnQkY29ob3J0X2lkIDwtIHBhc3RlMCh2YXJfY29ob3J0JGNvaG9ydF9pZCwgIiAobiA9ICIsIGFzLmNoYXJhY3Rlcih2YXJfY29ob3J0JHRvdF9jYXNlc19uKSwiKSIpCiAgdmFyX2NvaG9ydCA8LSB2YXJfY29ob3J0ICU+JSAKICAgIGdhdGhlcih2YXJpYWJsZSwgdmFsdWUsIDM6bmNvbCh2YXJfY29ob3J0KSkgJT4lIGdyb3VwX2J5KGNvaG9ydF9pZCwgdmFyaWFibGUpICU+JSBzdW1tYXJpemUocHJjdCA9IHZhbHVlL3RvdF9jYXNlc19uKjEwMCkKICB2YXJfY29ob3J0JHZhcmlhYmxlIDwtIHN1YigiX24iLCAiIiwgdmFyX2NvaG9ydCR2YXJpYWJsZSkKCmlmICghaXMubnVsbChleGNsdWRlX3NpbmdsZSkpewogIHZhcl9zaW5nbGUgPC0gZGZfc2luZ2xlY2FzZXMgJT4lIHNlbGVjdCgtY29udGFpbnMoZXhjbHVkZV9zaW5nbGUpKQogIHZhcl9zaW5nbGUgPC0gdmFyX3NpbmdsZSAlPiUgc2VsZWN0KGNvbnRhaW5zKGNvbG5hbWVfc2luZ2xlKSkKfSBlbHNlCnsKICB2YXJfc2luZ2xlIDwtIGRmX3NpbmdsZWNhc2VzICU+JSBzZWxlY3QoY29udGFpbnMoY29sbmFtZV9zaW5nbGUpKQp9CgogIyU+JSBzZWxlY3QoLWNvbnRhaW5zKCJhbnkiKSkKY29scyA8LSBzYXBwbHkodmFyX3NpbmdsZSwgaXMubG9naWNhbCkKdmFyX3NpbmdsZVssY29sc10gPC0gbGFwcGx5KHZhcl9zaW5nbGVbLGNvbHNdLCBhcy5udW1lcmljKQp2YXJfc2luZ2xlIDwtIGNvbFN1bXModmFyX3NpbmdsZSwgbmEucm0gPSBUUlVFKQp2YXJfc2luZ2xlIDwtIHZhcl9zaW5nbGUvbnJvdyhkZl9zaW5nbGVjYXNlcykqMTAwCnZhcl9zaW5nbGUgPC0gYXMuZGF0YS5mcmFtZSh2YXJfc2luZ2xlKSAlPiUgcm93bmFtZXNfdG9fY29sdW1uKCkKdmFyX3NpbmdsZSRjb2hvcnRfaWQgPC0gcGFzdGUwKCJzaW5nbGUgY2FzZXMgKG4gPSAiLCBuX3NpbmdsZV9jYXNlcywiKSIpCmNvbG5hbWVzKHZhcl9zaW5nbGUpIDwtIGMoInZhcmlhYmxlIiwgInByY3QiLCAiY29ob3J0X2lkIikKCgptaXNzaW5nIDwtIHNldGRpZmYodmFyX3NpbmdsZSR2YXJpYWJsZSwgdmFyX2NvaG9ydCR2YXJpYWJsZSkKaWYgKGxlbmd0aChtaXNzaW5nKSAhPSAwICl7CiAgbWlzc2luZ19kZiA8LSBkYXRhLmZyYW1lKHZhcmlhYmxlID0gbWlzc2luZywgcHJjdCA9IE5BLCBjb2hvcnRfaWQgPSB1bmlxdWUodmFyX2NvaG9ydCRjb2hvcnRfaWQpKQogIHZhcl9jb2hvcnQgPC0gYmluZF9yb3dzKHZhcl9jb2hvcnQsIGFzX3RpYmJsZShtaXNzaW5nX2RmKSkKfSBlbHNlIGlmIChsZW5ndGgobWlzc2luZykgPT0gMCkgewogIG1pc3NpbmcgPC0gc2V0ZGlmZih2YXJfY29ob3J0JHZhcmlhYmxlLCB2YXJfc2luZ2xlJHZhcmlhYmxlKQogIGlmIChsZW5ndGgobWlzc2luZykgIT0gMCl7CiAgbWlzc2luZ19kZiA8LSBkYXRhLmZyYW1lKHZhcmlhYmxlID0gbWlzc2luZywgcHJjdCA9IE5BLCBjb2hvcnRfaWQgPSB1bmlxdWUodmFyX3NpbmdsZSRjb2hvcnRfaWQpKQogIHZhcl9zaW5nbGUgPC0gYmluZF9yb3dzKHZhcl9zaW5nbGUsIGFzX3RpYmJsZShtaXNzaW5nX2RmKSkKICB9Cn0KCmhtX2NvaG9ydCA8LSBnZ3Bsb3QodmFyX2NvaG9ydCwgYWVzKHggPSB2YXJpYWJsZSwgeSA9IGNvaG9ydF9pZCwgZmlsbCA9IHByY3QpKSArIAogICAgZ2VvbV90aWxlKCkgKyB0aGVtZV9jbGFzc2ljKCkgKwogICAgdGhlbWUoYXhpcy50ZXh0Lng9ZWxlbWVudF9ibGFuaygpLCBheGlzLnRpY2tzLng9ZWxlbWVudF9ibGFuaygpLCBheGlzLmxpbmU9ZWxlbWVudF9ibGFuaygpKSsKICAgc2NhbGVfZmlsbF9ncmFkaWVudChsb3cgPSAieWVsbG93IiwgaGlnaD0icmVkIiwgbmEudmFsdWUgPSAibGlnaHRncmF5IiwgbGltaXRzID0gYygwLDEwMCkpICsKICAgIGxhYnMoeCA9ICIiLCB5ID0gImNvaG9ydCIsIHRpdGxlID1wbG90dGl0bGUpICsKICAgIGdlb21fdGV4dChhZXMobGFiZWw9cm91bmQocHJjdCwgMikpLCBzaXplID0gdGV4dHNpemUsIGNvbG9yID0gImJsYWNrIikKCmhtX3NpbmdsZSA8LSBnZ3Bsb3QodmFyX3NpbmdsZSwgYWVzKHggPSB2YXJpYWJsZSwgeSA9IGNvaG9ydF9pZCwgZmlsbCA9IHByY3QpKSArIAogICAgZ2VvbV90aWxlKCkgKyAgdGhlbWVfY2xhc3NpYygpICsKICAgIHRoZW1lKGF4aXMudGV4dC54PWVsZW1lbnRfdGV4dChhbmdsZT05MCwgaGp1c3Q9MSksIGF4aXMubGluZT1lbGVtZW50X2JsYW5rKCkpKwogICAgc2NhbGVfZmlsbF9ncmFkaWVudChsb3cgPSAieWVsbG93IiwgaGlnaCA9ICJyZWQiLCBuYS52YWx1ZSA9ICJsaWdodGdyYXkiLCBsaW1pdHMgPSBjKDAsMTAwKSkrIGxhYnMoeSA9ICJjb2hvcnQiKSArCiAgICBnZW9tX3RleHQoYWVzKGxhYmVsPXJvdW5kKHByY3QsIDIpKSwgc2l6ZSA9IHRleHRzaXplLCBjb2xvciA9ICJibGFjayIpIAoKcGxvdF9ncmlkKGhtX2NvaG9ydCwgaG1fc2luZ2xlLCBhbGlnbiA9ICJ2IiwgbnJvdyA9IDIsIHJlbF9oZWlnaHRzID0gYygxLzIsIDEvMikpCn0KYGBgCgojIFNlYXJjaCBzdHJhdGVneQoKRWxlY3Ryb25pYyBiaWJsaW9ncmFwaGljYWwgZGF0YWJhc2VzIHdlcmUgc2VhcmNoZWQsIGJvdGggaW5kZXhlZCAoUHViTWVkLCBFbWJhc2UpIGFuZCBwcmVwcmludCByZXBvc2l0b3JpZXMgKEJpb1J4aXYgYW5kIE1lZFJ4aXYpLiBBZGRpdGlvbmFsbHksIENPVklELTE5LXNwZWNpZmljIHJlc2VhcmNoIHJlcG9zaXRvcmllcyB3ZXJlIGJlIHNlYXJjaGVkIChDb2NocmFuZSBDT1ZJROKAkDE5IFN0dWR5IFJlZ2lzdGVyLCB0aGUgV29ybGQgSGVhbHRoIE9yZ2FuaXphdGlvbiAoV0hPKSBDT1ZJROKAkDE5IEdsb2JhbCBSZXNlYXJjaCBEYXRhYmFzZSkuIFB1YmxpY2F0aW9ucyBpbiBFbmdsaXNoIGxhbmd1YWdlIGJldHdlZW4gMzEgRGVjZW1iZXIgMjAxOSB1cCB0byAzMCBKdW5lIDIwMjAsIHdoZW4gdGhlIGZpbmFsIHNlYXJjaCB3YXMgY2FycmllZCBvdXQsIHdlcmUgcmV2aWV3ZWQgb24gZWxpZ2liaWxpdHkuIEJvdGggZmluaXNoZWQgYW5kIG9uZ29pbmcgc3R1ZGllcyB3ZXJlIGNvbnNpZGVyZWQuIFRoZSByZWZlcmVuY2UgbGlzdHMgb2YgdGhlIGluY2x1ZGVkIHN0dWRpZXMgd2VyZSBjb25zaWRlcmVkIGFzIGFuIGFkZGl0aW9uYWwgc291cmNlLiAKClNlYXJjaCBzdHJhdGVneSBmb2N1c2VkIG9uIGtleXdvcmRzIGludm9sdmluZyB0aGUgaHlwZXJpbmZsYW1tYXRvcnkgcHJlc2VudGF0aW9uIChQSU1TLVRTLCBNSVMtQywgaHlwZXJpbmZsYW1tYXRpb24sIEhMSCwgdG94aWMgc2hvY2sgc3luZHJvbWUsIHZhc2N1bGl0aXMsIEthd2FzYWtpIGRpc2Vhc2UpLCBhcyB3ZWxsIGFzIHRoZSBhc3NvY2lhdGlvbiB3aXRoIENPVklELTE5IChTQVJTLUNvVi0yLCBDT1ZJRC0xOSwgbm92ZWwgY29yb25hdmlydXMpIGFuZCB0aGUgcGVkaWF0cmljIHBvcHVsYXRpb24gKGNoaWxkcmVuLCBhZG9sZXNjZW50LCBwZWRpYXRyaWMpLiBTdHJ1Y3R1cmVkIGhpZXJhcmNoaWMga2V5d29yZHMgKE1lU0gsIEVtdHJlZSkgYW5kIHdpbGRjYXJkcyB3ZXJlIHVzZWQgd2hlbiBhcHBsaWNhYmxlLiBCb29sZWFuIG9wZXJhdG9ycyB3ZXJlIHVzZWQgdG8gY29tYmluZSB0aGUgdmFyaW91cyBrZXl3b3JkcyBvZiBpbnRlcmVzdC4gQmVsb3csIHRoZSBmdWxsIHNlYXJjaCB0ZXJtcyBhcmUgcHJlc2VudGVkIGZvciB0aGUgZGlmZmVyZW50IGRhdGFiYXNlcykuIAoKIyMgUHViTWVkIAoKYGBgCijigJxQSU1TKuKAnSBPUiDigJxNSVMq4oCd4oCvT1Ig4oCcbXVsdGlzeXN0ZW3igK9pbmZsYW1tYXQq4oCd4oCvT1Ig4oCcaHlwZXJpbmZsYW1tYXQq4oCdIE9SIOKAnGluZmxhbW1hdG9yeSBkaXNlYXNl4oCdIE9SIOKAnHN5c3RlbWlj4oCvaW5mbGFtbWF0KuKAneKAr09SIOKAnGN5dG9raW5lIHJlbGVhc2XigJ0gT1Ig4oCcS2F3YXNha2kq4oCdIE9SIOKAnHZhc2N1bGl0aXPigJ0gT1Ig4oCcdG94aWMgc2hvY2vigJ3igK9PUiDigJxzaG9ja+KAnSBPUiAoInBlZGlhdHJpY+KAr211bHRpc3lzdGVtIGluZmxhbW1hdG9yeSBkaXNlYXNlLCBDT1ZJRC0xOSByZWxhdGVkIiBbU3VwcGxlbWVudGFyeSBDb25jZXB0XSkgT1IgIk11Y29jdXRhbmVvdXPigK9MeW1waCBOb2RlIFN5bmRyb21lIltNZXNoXSBPUiAiU2hvY2siW01lc2hdIE9SICJWYXNjdWxpdGlzIltNZXNoXSBPUiDigJxpbmZsYW1tYXRpb27igJ1bTWVTSF0p4oCvQU5E4oCvKOKAnGNvdmlkKuKAnSBvciDigJxzYXJzLWNvdi0y4oCdIG9yIOKAnDIwMTktbkNvduKAnSBvciDigJxub3ZlbCBjb3JvbmF2aXJ1c+KAnSBvciDigJxjb3JvbmF2aXJ1cyBkaXNlYXNl4oCdIG9y4oCvIkNPVklELTE5IiBbU3VwcGxlbWVudGFyeSBDb25jZXB0XSBPUuKAryJzZXZlcmUgYWN1dGUgcmVzcGlyYXRvcnkgc3luZHJvbWUgY29yb25hdmlydXMgMiIgW1N1cHBsZW1lbnRhcnkgQ29uY2VwdF0pIEFOROKAryjigJxjaGlsZCrigJ0gb3Ig4oCcYWRvbGVzY2VuKuKAnSBvciDigJx0ZWVuKuKAnSBvciDigJxwZWRpYXRyaWMq4oCdIG9yIOKAnGluZmFudOKAnSBvciDigJxuZXdib3Ju4oCdIG9y4oCvIkNoaWxkIltNZXNoXeKAr09S4oCvIkFkb2xlc2NlbnQiW01lc2hdIE9S4oCvIlBlZGlhdHJpY3MiW01lc2hd4oCvb3IgIkluZmFudCzigK9OZXdib3JuIltNZXNoXeKAr29y4oCvIkluZmFudCJbTWVzaF0pIEFORCAoIjIwMTkvMTIvMzEiW0RhdGUgLSBQdWJsaWNhdGlvbl0gOiAiMzAwMCJbRGF0ZSAtIFB1YmxpY2F0aW9uXSnigK8gCmBgYAoKIyMgRW1iYXNlICAKCmBgYAooJ3BpbXMqJyBPUiAnbWlzJ+KAr09SIOKAmG1pcy1j4oCZ4oCvT1IgJ211bHRpc3lzdGVt4oCvaW5mbGFtbWF0KicgT1IgJ2h5cGVyaW5mbGFtbWF0KicgT1IgJ2luZmxhbW1hdG9yeSBkaXNlYXNlJyBPUiAnc3lzdGVtaWPigK9pbmZsYW1tYXQqJyBPUiAnY3l0b2tpbmUgcmVsZWFzZScgT1IgJ2thd2FzYWtpKicgT1IgJ3Zhc2N1bGl0aXMnIE9SICd0b3hpYyBzaG9jaycgT1IgJ3Nob2NrJykgQU5EICgnY292aWQqJyBPUiAnc2Fycy1jb3YtMicgT1IgJzIwMTktbmNvdicgT1IgJ25vdmVsIGNvcm9uYXZpcnVzJyBPUiAnY29yb25hdmlydXMgZGlzZWFzZScpIEFORCAoJ2NoaWxkKicgT1IgJ2Fkb2xlc2NlbionIE9SICd0ZWVuKicgT1IgJ3BlZGlhdHJpYyonIE9SICdpbmZhbnQnIE9SICduZXdib3JuJykgQU5EIFszMS0xMi0yMDE5XS9zZOKAryAKYGBgCgojIyBCaW9SeGl2IGFuZCBNZWRSeGl2IApMaXRlcmF0dXJlIHNlYXJjaCBpbiBiaW9yeGl2IGFuZCBtZWRyeGl2IHdhcyBkb25lIHdpdGggdGhlIFIgYnkgZG93bmxvYWRpbmcgdGhlIGRhdGEgZnJvbSB0aGUgZGVkaWNhdGVkIFtDT1ZJRC0xOSBTQVJTLUNvVi0yIHByZXByaW50cyBwYWdlXShodHRwczovL2Nvbm5lY3QuYmlvcnhpdi5vcmcvcmVsYXRlL2NvbnRlbnQvMTgxKSBpbiBqc29uIGZvcm1hdCwgYW5kIGNhbiBiZSBmb3VuZCBvbiBbR2l0aHViXShodHRwczovL2dpdGh1Yi5jb20vcm12cGFlbWUvUElNU19UUy9ibG9iL21hc3Rlci9wcmVwcmludF9zZWFyY2guUikuCgoKIyMgQ29jaHJhbmUgQ09WSUQtMTkgc3R1ZHkgcmVnaXN0ZXIgCgpgYGAKKHBpbXMqIE9SIG1pcyBPUiAibWlzLWMiIE9SICJtdWx0aXN5c3RlbSBpbmZsYW1tYXQqIiBPUiBoeXBlcmluZmxhbW1hdCogT1IgImluZmxhbW1hdG9yeSBkaXNlYXNlIiBPUiAic3lzdGVtaWMgaW5mbGFtbWF0KiIgT1IgImN5dG9raW5lIHJlbGVhc2UiIE9SIGthd2FzYWtpKiBPUiB2YXNjdWxpdGlzIE9SICJ0b3hpYyBzaG9jayIgT1Igc2hvY2spIEFORCAoY2hpbGQqIE9SIGFkb2xlc2NlbiogT1IgdGVlbiogT1IgcGVkaWF0cmljKiBPUiBpbmZhbnQgT1IgbmV3Ym9ybikgCmBgYAoKIyMgV0hPIENPVklELTE5IEdsb2JhbCBsaXRlcmF0dXJlIG9uIGNvcm9uYXZpcnVzIGRpc2Vhc2UgCgpgYGAKKCJwaW1zKiIgT1IgIm1pcyIgT1IgIm1pcy1jIiBPUiAibXVsdGlzeXN0ZW3igK9pbmZsYW1tYXQqIiBPUiAiaHlwZXJpbmZsYW1tYXQqIiBPUiAiaW5mbGFtbWF0b3J5IGRpc2Vhc2UiIE9SICJzeXN0ZW1pY+KAr2luZmxhbW1hdCoiIE9SICJjeXRva2luZSByZWxlYXNlIiBPUiAia2F3YXNha2kqIiBPUiAidmFzY3VsaXRpcyIgT1IgInRveGljIHNob2NrIiBPUiAic2hvY2siKSBBTkQgKCJjaGlsZCoiIE9SICJhZG9sZXNjZW4qIiBPUiAidGVlbioiIE9SICJwZWRpYXRyaWMqIiBPUiAiaW5mYW50IiBPUiAibmV3Ym9ybiIpIApgYGAKCiMgU3R1ZHkgc2VsZWN0aW9uIGFuZCByaXNrIG9mIGJpYXMgYXNzZXNzbWVudApPcmlnaW5hbCBzdHVkaWVzIHdlcmUgaW5jbHVkZWQgd2l0aCBmb2xsb3dpbmcgZGVzaWduczogUkNULCBvYnNlcnZhdGlvbmFsIHN0dWRpZXMsIGNhc2UtY29udHJvbCBzdHVkaWVzLCBjcm9zcy1zZWN0aW9uYWwgc3R1ZGllcywgY2FzZSByZXBvcnRzIGFuZCBjYXNlIHNlcmllcy4gCgpSZWNvcmRzIGVsaWdpYmxlIGZvciBpbmNsdXNpb24gc2hvdWxkIHByZXNlbnQgY2xpbmljYWwgY2FzZXMgZnVsZmlsbGluZyB0aGUgZm9sbG93aW5nIDMgY3JpdGVyaWE6IAoKSW5jbHVzaW9uIGNyaXRlcmlhCgoxLglTdHVkeSBwb3B1bGF0aW9uOiBoeXBlcmluZmxhbW1hdG9yeSBzeW5kcm9tZSBtZWV0aW5nIHRoZSBjYXNlIGRlZmluaXRpb25zIG9mIFBJTVMtVFMgb3IgTUlTKC1DKSBpbiBjaGlsZHJlbiAoMC0xOSB5ZWFycyBvZiBhZ2UpIHdpdGggYSB0ZW1wb3JhbCBhc3NvY2lhdGlvbiB3aXRoIGNvbmZpcm1lZCBvciBwcm9iYWJsZSBDT1ZJRC0xOQoyLglPdXRjb21lOiBjbGluaWNhbCwgZXBpZGVtaW9sb2dpY2FsIGFuZCBpbW11bm9sb2dpY2FsIGRlc2NyaXB0aW9ucywgdGhlcmFwZXV0aWMgbWFuYWdlbWVudCBhbmQgY2xpbmljYWwgZWZmZWN0LCBhbmQgcHJvZ25vc2lzIG9mIGluZGl2aWR1YWxzIG9yIGNvaG9ydHMgb2YgcGF0aWVudHMuCjMuCVR5cGVzIG9mIHN0dWR5IGRlc2lnbnM6IFJDVCwgb2JzZXJ2YXRpb25hbCBzdHVkaWVzLCBjYXNlLWNvbnRyb2wgc3R1ZGllcywgY3Jvc3Mtc2VjdGlvbmFsIHN0dWRpZXMsIGNhc2UgcmVwb3J0cyBhbmQgY2FzZSBzZXJpZXMKCkV4Y2x1c2lvbiBjcml0ZXJpYQoxLglTdHVkaWVzIG9uIGFkdWx0IHBhdGllbnRzIHdpdGggU0FSUy1Db1YtMiBpbmZlY3Rpb24gYW5kL29yIFNBUlMtQ29WLTIgYXNzb2NpYXRlZCBoeXBlcmluZmxhbW1hdG9yeSBzeW5kcm9tZXMKMi4JU3R1ZGllcyBvbiBwZWRpYXRyaWMgcGF0aWVudHMgd2l0aCBvdGhlciBjb3JvbmF2aXJ1cyBpbmZlY3Rpb25zIChTQVJTLUNvVi0xIGFuZCBNaWRkbGUgRWFzdCBSZXNwaXJhdG9yeSBTeW5kcm9tZSBDb3JvbmF2aXJ1cyAoTUVSUy1Db1YpIGluZmVjdGlvbiBvciBvdGhlciByZXNwaXJhdG9yeSBpbmZlY3Rpb25zLgozLglTdHVkaWVzIHdpdGggaW5jb21wbGV0ZSBvciBsYWNraW5nIG5lY2Vzc2FyeSBkYXRhIAo0LglEdXBsaWNhdGUgc3R1ZGllcwo1LglTdHVkaWVzIHdpdGhvdXQgYWNjZXNzaWJsZSBmdWxsIHRleHQgdmVyc2lvbnMKNi4JU3R1ZGllcyBub3QgaW4gRW5nbGlzaCBsYW5ndWFnZQoKU3R1ZHkgc2VsZWN0aW9uIHdhcyBhIHR3by1zdGFnZSBwcm9jZXNzIHdpdGgsIGZpcnN0LCB0aXRsZXMgYW5kIGFic3RyYWN0cyBvZiBzdHVkaWVzIHNjcmVlbmVkIHdpdGggcmV0cmlldmFsIHVzaW5nIHRoZSBzZWFyY2ggc3RyYXRlZ3kgYW5kIHRoZW4sIHNlY29uZCwgZnVsbCB0ZXh0IHNjcmVlbmluZyBvZiBwb3RlbnRpYWxseSBlbGlnaWJsZSBzdHVkaWVzIGFzc2Vzc2VkIGJ5IHR3byByZXZpZXdlcnMgaW5kZXBlbmRlbnRseS4gQW55IGRpc2FncmVlbWVudCBvdmVyIHRoZSBlbGlnaWJpbGl0eSBvZiBwYXJ0aWN1bGFyIHN0dWRpZXMgd2FzIHJlc29sdmVkIHRocm91Z2ggZGlzY3Vzc2lvbiB3aXRoIGEgdGhpcmQgcmV2aWV3ZXIuIAoKVGhlIFByZWZlcnJlZCBSZXBvcnRpbmcgSXRlbXMgZm9yIFN5c3RlbWF0aWMgUmV2aWV3cyBhbmQgTWV0YS1BbmFseXNlcyAoUFJJU01BKSBjaGVja2xpc3Qgd2FzIHVzZWQgdG8gZ3VpZGUgdGhlIHN0dWR5IHNlbGVjdGlvbiBhbmQgZXh0cmFjdGlvbiBwcm9jZXNzLiBSaXNrIGZvciBiaWFzIG9uIGVsaWdpYmxlIG9ic2VydmF0aW9uYWwgc3R1ZGllcyB3ZXJlIGFzc2Vzc2VkIGJ5IExIIGFjY29yZGluZyB0byB0aGUgTmV3Q2FzdGxlLU90dGF3YSBTY2FsZSAoTk9TKSwgd2l0aCBmdWxsIHZlcmlmaWNhdGlvbiBvZiBhbGwganVkZ21lbnRzIGJ5IFJWUC4gTGV2ZWwgb2YgZXZpZGVuY2Ugd2FzIHJhdGVkIGFjY29yZGluZyB0byBTYWNrZXR0LgoKCiMgUFJJU01BIGZsb3cgZGlhZ3JhbQoKIVtdKC4vcGxvdHMvUFJJU01BIDIwMDkgZmxvdyBkaWFncmFtLnBuZykKCiMgRGF0YSBleHRyYWN0aW9uCkFsbCBvcmlnaW5hbCBzdHVkaWVzIGRlc2NyaWJpbmcgY2xpbmljYWzigK9jYXNlc+KAr21lZXRpbmcgdGhlIGNhc2UgZGVmaW5pdGlvbuKAr29mIFBJTVMtVFMs4oCvYXMgZGVmaW5lZCBieSBSQ1BDSCzigK93ZXJlIGVsaWdpYmxlIGZvciBpbmNsdXNpb24uIFByaW1hcnkgb3V0Y29tZSBhbmFseXNpcyBmb2N1c2VkIG9uIGNsaW5pY2FsLCBlcGlkZW1pb2xvZ2ljYWwgYW5kIGltbXVub2xvZ2ljYWwgbWFuaWZlc3RhdGlvbnMsIHRoZXJhcGV1dGljIG1hbmFnZW1lbnQgYW5k4oCvcHJvZ25vc2lzLuKAryAKClRoZSBmb2xsb3dpbmcgZGF0YSBwb2ludHMgd2VyZSBvdXRsaW5lZCB0byBiZSBleHRyYWN0ZWQgb3V0IG9mIGVsaWdpYmxlIHJlY29yZHM6IHBhdGllbnQgY2hhcmFjdGVyaXN0aWNzIChlLmcuIHNleCwgYWdlLCBldGhuaWNpdHksIGFudGhyb3BvbWV0cnks4oCmKSwgY29tb3JiaWRpdGllcyAoZS5nLiBjYXJkaW92YXNjdWxhciBkaXNlYXNlLCByZXNwaXJhdG9yeSBkaXNlYXNlLCBkaWFiZXRlcyBtZWxsaXR1cywgcmVuYWwgZGlzZWFzZSwgbWFsaWduYW5jeS9jYW5jZXIsIGltbXVub2RlZmljaWVuY3ks4oCmKSwgU0FSUy1Db1YtMiBpbmZlY3Rpb24gcmVsYXRlZCBkYXRhIChlLmcuIGNsb3NlIGNvbnRhY3RzIHdpdGggY29uZmlybWVkIG9yIHN1c3BlY3RlZCBDT1ZJRC0xOSwgUENSIGFuZCBzZXJvbG9neSByZXN1bHRzLOKApiksIGNsaW5pY2FsIHN5bXB0b21zIChlLmcuIGZldmVyLCByZXNwaXJhdG9yeSwgZ2FzdHJvLWludGVzdGluYWwsIG5ldXJvbG9naWNhbCwgZGVybWF0b2xvZ2ljYWwsIHJlbmFsIG9yIGNhcmRpYWMgbWFuaWZlc3RhdGlvbnMsIGRlc2NyaXB0aW9uIG9mIEthd2FzYWtpIGNyaXRlcmlhLOKApiksIGxhYm9yYXRvcnkgdGVzdHMgYXQgdmFyaW91cyB0aW1lIHBvaW50cyAoZS5nLiBoYWVtb2dsb2JpbiwgV0JDLCBseW1waG9jeXRlLCBuZXV0cm9waGlsIGFuZCBwbGF0ZWxldCBjb3VudHMsIHNvZGl1bSwgZmVycml0aW4sIEQtZGltZXIsIGZpYnJpbm9nZW4sIGFsYnVtaW4sIGNyZWF0aW5pbmUsIGxpdmVyIHRyYW5zYW1pbmFzZXMsIENLLCBMREgsIHRyb3BvbmluLCBOVC1wcm9CTlAsIENSUCwgRVNSLCBzZXJ1bSBjeXRva2luZXMsIGNvbXBsZW1lbnQsIGltbXVub2dsb2J1bGlucyzigKYpLCByYWRpb2xvZ2ljYWwgcmVzdWx0cywgaG9zcGl0YWwgYWRtaXNzaW9uIGRhdGEgKGRheXMgb2YgaG9zcGl0YWxpc2F0aW9uLCBkYXlzIG9mIElDVSBjYXJlLOKApiksIGNyaXRpY2FsIGNhcmUgaW50ZXJ2ZW50aW9ucyAoaW52YXNpdmUgYW5kIG5vbi1pbnZhc2l2ZSB2ZW50aWxhdGlvbiwgaW5vdHJvcGVzL3Zhc29wcmVzc29ycyB1c2UsIEVDTU8s4oCmKSBhbmQgdGhlcmFwZXV0aWNzIGFuZCB0aGVpciBlZmZlY3QgKGNvcnRpY29zdGVyb2lkcywgYXNwaXJpbiwgSVZJRywgYmlvdGhlcmFwZXV0aWNzLCBhbnRpYmlvdGljcyzigKYpLiBGaWVsZHMgd2l0aCBpbnN1ZmZpY2llbnQgZGF0YSB3aWxsIGJlIGV4Y2x1ZGVkIGZyb20gZmluYWwgYW5hbHlzaXMuIEFkZGl0aW9uYWwgcGFyYW1ldGVycyB3ZXJlIGluY2x1ZGVkIGlmIHJlbGV2YW50LiAKCgpDYXNlcyB3ZXJlIGV4Y2x1ZGVkIGlmIGluc3VmZmljaWVudCBkYXRhIHN1Z2dlc3RpbmcgYSB0ZW1wb3JhbCBhc3NvY2lhdGlvbiB3aXRoIFNBUlMtQ29WLTIgd2FzIHByZXNlbnRlZC4gQSByZWNlbnQgb3IgY3VycmVudCBwb3NpdGl2ZSBTQVJTLUNvVi0yIFBDUiAobmFzb3BoYXJ5bmdlYWwsIGZlY2FsLCBvdGhlcikgb3Igc2Vyb2xvZ3kgKElnQSwgSWdNLCBJZ0cpIHJlc3VsdHMgbmVlZGVkIHRvIGJlIHByZXNlbnRlZCwgb3IgaGlzdG9yeSBvZiBjbG9zZSBjb250YWN0IChlLmcuIGhvdXNlaG9sZCkgd2l0aCBhIGNvbmZpcm1lZCBvciBoaWdobHkgc3VzcGVjdCBjYXNlIG9mIENPVklELTE5IHdhcyByZXF1aXJlZC4gU3R1ZGllcyB3ZXJlIGV4Y2x1ZGVkIGlmIGRhdGEgd2FzIGluY29uc2lzdGVudGx5IHByZXNlbnRlZC4gCgoKQXMgYSBzZWNvbmRhcnkgb3V0Y29tZSwgaXQgd2FzIG91dGxpbmVkIHRvIG1ha2UgYSBxdWFsaXRhdGl2ZSBhc3Nlc3NtZW50IGFuZCBwcm9wb3NlIGFuIGltbXVub2xvZ2ljYWwgbWVjaGFuaXNtIHVuZGVycGlubmluZyB0aGlzIGluZmxhbW1hdG9yeSBzeW5kcm9tZSBiYXNlZCBvbiB0aGUgY2FzZXMgcmVwb3J0ZWQgaW4gbGl0ZXJhdHVyZSBhbmQvb3IgaW1tdW5vbG9naWNhbCBpbnZlc3RpZ2F0aW9ucyBwZXJmb3JtZWQgaW4gdGhlc2UgYWZmZWN0ZWQgY2hpbGRyZW4uIE5ldmVydGhlbGVzcywgdXAgdG8gdGhlIGZpbmFsIHNlYXJjaCwgaW5zdWZmaWNpZW50IGRhdGEgd2FzIGF2YWlsYWJsZSB0byBjb25kdWN0IHN1Y2ggYXNzZXNzbWVudHMuICAKCkEgc2luZ2xlIHJldmlld2VyIChMSCkgZXh0cmFjdGVkIGRhdGEgdXNpbmcgYSBzdGFuZGFyZGl6ZWQgZm9ybSwgd2hpbGUgYSBzZWNvbmQgcmV2aWV3ZXIgKFJWUCkgY3Jvc3MgY2hlY2tlZCBhbGwgZGF0YSBmb3IgY29ycmVjdG5lc3MgYW5kIGNvbXBsZXRlbmVzcy4gQW55IGRpc2FncmVlbWVudCBvdmVyIHN0dWR5IGVsaWdpYmlsaXR5IGFuZCBjb25mbGljdCBvbiBkYXRhIGV4dHJhY3Rpb24gd2VyZSByZXNvbHZlZCBieSBhIHRoaXJkIHJldmlld2VyIChGSCkuIAoKQ29ob3J0IHN0dWRpZXMgYW5kIHN0dWRpZXMgcmVwb3J0aW5nIG9uIHNpbmdsZSBjYXNlcyB3ZXJlIGFuYWx5c2VkIHNlcGFyYXRlbHksIGFzIHdlIGRpZCBub3QgaGF2ZSBhY2Nlc3MgdG8gdGhlIGluZGl2aWR1YWwgY2FzZSBjaGFyYWN0ZXJpc3RpY3Mgb2YgdGhlIGNvaG9ydCBzdHVkaWVzLiAgRm9yIHRoZSBjb2hvcnQgc3R1ZGllcywgcHJvcG9ydGlvbnMgd2VyZSBjYWxjdWxhdGVkIGJ5IHN1bW1pbmcgb25seSB0aGUgc3R1ZGllcyB3aGljaCByZXBvcnQgb24gdGhlIHZhcmlhYmxlLCBleGNlcHQgZm9yIHJhcmUgY29uZGl0aW9ucyBzdWNoIGFzIGRlYXRoLCBjb21vcmJpZGl0aWVzLCB1c2Ugb2YgRUNNTyBvciBiaW9waGFybWFjZXV0aWNhbHMuCgojIERhdGEgaW1wb3J0IGFuZCBjbGVhbmluZwojIyBTaW5nbGUgY2FzZXMKQWZ0ZXIgZGF0YSBjb2xsZWN0aW9uLCB3ZSBpbXBvcnQgdGhlIHNpbmdsZSBjYXNlcyBmcm9tIHRoZSBbZ2VuZXJhbCBleGNlbCBzaGVldF0oKSBhbmQgdHJhbnNmb3JtIHRoZSBleGNlbCBzaGVldCBzbyB0aGF0IHZhcmlhYmxlcyBhcmUgY29sdW1ucyBhbmQgcm93cyBhcmUgY2FzZXMuIENvbHVtbnMgd2l0aG91dCBhbnkgdmFsdWVzIGFyZSBhbHNvIHJlbW92ZWQuIAoKVGhlIHNpbmdsZSBjYXNlcyBmcm9tIFBvdWxldHR5ICgxMC4xMTM2L2FubnJoZXVtZGlzLTIwMjAtMjE3OTYwKSBhcmUgZXhjbHVkZWQgKGFzIHRoZXkgYXJlIGluY2x1ZGVkIGluIHRoZSBjb2hvcnRzKS4KCgpgYGB7cn0KZGZfc2luZ2xlY2FzZXMgPC0KICByZWFkX2V4Y2VsKCIvVXNlcnMvcm12cGFlbWUvT25lZHJpdmUvVUdlbnQvUElNUy1UUyBTeXN0ZW1hdGljIFJldmlldyAtIERhdGEgZXh0cmFjdGllL2RhdGEgZXh0cmFjdGllLnhsc3giLAogICAgICAgICAgICAgc2hlZXQgPSAiU2luZ2xlIGNhc2VzIiwKICAgICAgICAgICAgIHNraXAgPSAxLAogICAgICAgICAgICAgY29sX25hbWVzID0gRkFMU0UpWywtYygxOjIpXQpkZl9zaW5nbGVjYXNlcyA8LSBkZl9zaW5nbGVjYXNlcyAlPiUgdCgpCmRmX3NpbmdsZWNhc2VzIDwtIGFzLmRhdGEuZnJhbWUoZGZfc2luZ2xlY2FzZXMsIHN0cmluZ3NBc0ZhY3RvcnMgPSBGQUxTRSkKbm1zIDwtIGFzLnZlY3RvcihkZl9zaW5nbGVjYXNlc1sxLF0pCm5tc1tpcy5uYShubXMpXSA8LSAndG1wJwpjb2xuYW1lcyhkZl9zaW5nbGVjYXNlcykgPC0gbWFrZS51bmlxdWUoYXMuY2hhcmFjdGVyKG5tcykpCmRmX3NpbmdsZWNhc2VzIDwtIGRmX3NpbmdsZWNhc2VzWy0xLF0KZGZfc2luZ2xlY2FzZXMgPC0gZGZfc2luZ2xlY2FzZXMgJT4lIHNlbGVjdCgtY29udGFpbnMoInRtcCIpKQpkZl9zaW5nbGVjYXNlcyA8LSBkZl9zaW5nbGVjYXNlcyAlPiUgc2VsZWN0KC12YXJpYWJsZV9pZCkKCmRmX3NpbmdsZWNhc2VzIDwtIGRmX3NpbmdsZWNhc2VzICU+JSAKICBtdXRhdGVfYWxsKGZ1bnMoc3RyX3JlcGxhY2UoLiwgIlllcyIsICJ5ZXMiKSkpCmRmX3NpbmdsZWNhc2VzIDwtIGRmX3NpbmdsZWNhc2VzICU+JSAKICBtdXRhdGVfYWxsKGZ1bnMoc3RyX3JlcGxhY2UoLiwgIk5vIiwgIm5vIikpKQpkZl9zaW5nbGVjYXNlcyA8LSBkZl9zaW5nbGVjYXNlcyAlPiUgCiAgbXV0YXRlX2FsbChmdW5zKHN0cl9yZXBsYWNlKC4sICJwb3MiLCAieWVzIikpKQpkZl9zaW5nbGVjYXNlcyA8LSBkZl9zaW5nbGVjYXNlcyAlPiUgCiAgbXV0YXRlX2FsbChmdW5zKHN0cl9yZXBsYWNlKC4sICJuZWciLCAibm8iKSkpCgpkZl9zaW5nbGVjYXNlcyA8LSBkZl9zaW5nbGVjYXNlcyAlPiUKICByZXBsYWNlX3dpdGhfbmFfYWxsKGNvbmRpdGlvbiA9IH4ueCA9PSAiTkEiKQoKZGZfc2luZ2xlY2FzZXMgPC0gdHlwZV9jb252ZXJ0KGRmX3NpbmdsZWNhc2VzKQpkZl9zaW5nbGVjYXNlc19pbmNsUG91bGV0dHkgPC0gZGZfc2luZ2xlY2FzZXMKZGZfc2luZ2xlY2FzZXMgPC0gZGZfc2luZ2xlY2FzZXMgJT4lIGZpbHRlcihkb2kgIT0gImh0dHBzOi8vMTAuMTEzNi9hbm5yaGV1bWRpcy0yMDIwLTIxNzk2MCIpICAjIHRoZXNlIGNhc2VzIGFyZSBleGNsdWRlZCBhY2NvcmRpbmcgdG8gdGhlIGRhdGEgc2hlZXQKCmRmX3NpbmdsZWNhc2VzIDwtIGRmX3NpbmdsZWNhc2VzW2NvbFN1bXMoIWlzLm5hKGRmX3NpbmdsZWNhc2VzKSkgPiAwXQpuX3NpbmdsZV9jYXNlcyA8LSBucm93KGRmX3NpbmdsZWNhc2VzKQpgYGAKCgojIyMgTWFraW5nIHN1bW1hcnkgc3RhdGlzdGljcwoKSW4gdGhpcyBzZWN0aW9uLCBkYXRhIGlzIHN1bW1hcml6ZWQuIEZvciBleGFtcGxlLCBpZiB0aGVyZSBhcmUgYW55IGNvbW9yYmlkaXRpZXMgcHJlc2VudCwgYSBjb2x1bW4gImNvbW9yYl9hbnkiIGlzIGFkZGVkIGFuZCBhbm5vdGF0ZWQgYXMgVFJVRS4gVGhlIHNhbWUgaXMgZG9uZSBmb3IgQ09WSUQgc2Vyb2xvZ3kgYW5kIHN5bXB0b21zIG9mIG1ham9yIG9yZ2FuIChyZXNwaXJhdG9yeSwgY2FyZGlvdmFzY3VsYXIgZXRjKS4KCmBgYHtyfQpkZl9zaW5nbGVjYXNlcyA8LSBkZl9zaW5nbGVjYXNlcyAlPiUgbXV0YXRlKGNvbW9yYl9hbnkgPSBhcHBseShkZl9zaW5nbGVjYXNlcyAlPiUgc2VsZWN0KGNvbnRhaW5zKCJjb21vcmIiKSksIDEsIGFueSkpCmRmX3NpbmdsZWNhc2VzIDwtIGRmX3NpbmdsZWNhc2VzICU+JSBtb3ZlbWUoLiwgImNvbW9yYl9hbnkgYmVmb3JlIGNvbW9yYl9jYXJkaW92YXNjIikKYGBgCgpJZiBJZ0csIElnQSwgSWdNIG9yIENPVklEIHNlcm9sb2d5IGlzIHJlcG9ydGVkIGFzIHBvc2l0aXZlLCB0aGUgY29sdW1uIGNvdmlkX3Nlcm9fYW55IGlzIGFubm90YXRlZCBhcyBUUlVFLgoKYGBge3J9CmRmX3NpbmdsZWNhc2VzIDwtIGRmX3NpbmdsZWNhc2VzICU+JSBtdXRhdGUoY292aWRfc2Vyb19hbnkgPSBhcHBseShkZl9zaW5nbGVjYXNlcyAlPiUgc2VsZWN0KGNvdmlkX3Nlcm9fcG9zLCBjb3ZpZF9JZ0FfcG9zLCBjb3ZpZF9JZ01fcG9zLCBjb3ZpZF9JZ0dfcG9zKSwgMSwgYW55KSkKCmRmX3NpbmdsZWNhc2VzIDwtIGRmX3NpbmdsZWNhc2VzICU+JSBtb3ZlbWUoLiwgImNvdmlkX3Nlcm9fYW55IGJlZm9yZSBjb3ZpZF9zZXJvX3BvcyIpCmBgYAoKSWYgUENSKywgc3Rvb2wgUENSKywgSWdHLCBJZ0EsIElnTSBvciBDT1ZJRCBzZXJvbG9neSBpcyByZXBvcnRlZCBhcyBwb3NpdGl2ZSwgdGhlIGNvbHVtbiBjb3ZpZF9wb3NfYW55IGlzIGFubm90YXRlZCBhcyBUUlVFLgoKYGBge3J9CmRmX3NpbmdsZWNhc2VzIDwtIGRmX3NpbmdsZWNhc2VzICU+JSBtdXRhdGUoY292aWRfcG9zX2FueSA9IGFwcGx5KGRmX3NpbmdsZWNhc2VzICU+JSBzZWxlY3QoY292aWRfUENSX3BvcywgY292aWRfUENSX3N0b29sX3BvcywgY292aWRfc2Vyb19wb3MsIGNvdmlkX0lnQV9wb3MsIGNvdmlkX0lnTV9wb3MsIGNvdmlkX0lnR19wb3MpLCAxLCBhbnkpKQoKZGZfc2luZ2xlY2FzZXMgPC0gZGZfc2luZ2xlY2FzZXMgJT4lIG1vdmVtZSguLCAiY292aWRfcG9zX2FueSBiZWZvcmUgY292aWRfc2Vyb19hbnkiKQpgYGAKCklmIGFueSByZXNwaXJhdG9yeSBzeW1wdG9tcywgc3ltcF9yZXNwX2FueSBpcyBhbm5vdGF0ZWQgYXMgVFJVRS4KCmBgYHtyfQpkZl9zaW5nbGVjYXNlcyA8LSBkZl9zaW5nbGVjYXNlcyAlPiUgbXV0YXRlKHN5bXBfcmVzcF9hbnkgPSBhcHBseShkZl9zaW5nbGVjYXNlcyAlPiUgc2VsZWN0KHN5bXBfcmVzcF9OUywgc3ltcF9yZXNwX1VSVCwgc3ltcF9yZXNwX2R5c3BuZWEsIHN5bXBfcmVzcF9wbmV1bW9uaWEsIHN5bXBfcmVzcF9mYWlsdXJlLCBzeW1wX3Jlc3BfY2hlc3RwYWluKSwgMSwgYW55KSkKCmRmX3NpbmdsZWNhc2VzIDwtIGRmX3NpbmdsZWNhc2VzICU+JSBtb3ZlbWUoLiwgInN5bXBfcmVzcF9hbnkgYmVmb3JlIHN5bXBfcmVzcF9OUyIpCmBgYAoKSWYgYW55IEdJIHN5bXB0b21zLCBzeW1wX0dJX2FueSBpcyBhbm5vdGF0ZWQgYXMgVFJVRS4KCmBgYHtyfQpkZl9zaW5nbGVjYXNlcyA8LSBkZl9zaW5nbGVjYXNlcyAlPiUgbXV0YXRlKHN5bXBfR0lfYW55ID0gYXBwbHkoZGZfc2luZ2xlY2FzZXMgJT4lIHNlbGVjdChjb250YWlucygic3ltcF9HSSIpKSwgMSwgYW55KSkKCmRmX3NpbmdsZWNhc2VzIDwtIGRmX3NpbmdsZWNhc2VzICU+JSBtb3ZlbWUoLiwgInN5bXBfR0lfYW55IGJlZm9yZSBzeW1wX0dJX05TIikKYGBgCgpJZiBhbnkgbmV1cm9sb2dpY2FsIHN5bXB0b21zLCBzeW1wX25ldXJvX2FueSBpcyBhbm5vdGF0ZWQgYXMgVFJVRS4KCmBgYHtyfQpkZl9zaW5nbGVjYXNlcyA8LSBkZl9zaW5nbGVjYXNlcyAlPiUgbXV0YXRlKHN5bXBfbmV1cm9fYW55ID0gYXBwbHkoZGZfc2luZ2xlY2FzZXMgJT4lIHNlbGVjdChzeW1wX25ldXJvX2hlYWRhY2hlLHN5bXBfbmV1cm9fbWVuaW5naXRpcyxzeW1wX25ldXJvX21lbmluZ2lzbSxzeW1wX25ldXJvX2FzdGhlbmlhLHN5bXBfbmV1cm9faXJyaXRhYiksIDEsIGFueSkpCgpkZl9zaW5nbGVjYXNlcyA8LSBkZl9zaW5nbGVjYXNlcyAlPiUgbW92ZW1lKC4sICJzeW1wX25ldXJvX2FueSBiZWZvcmUgc3ltcF9uZXVyb19HQ1MiKQpgYGAKCklmIGFueSByZW5hbCBzeW1wdG9tcywgc3ltcF9yZW5hbF9hbnkgaXMgYW5ub3RhdGVkIGFzIFRSVUUuCgpgYGB7cn0KZGZfc2luZ2xlY2FzZXMgPC0gZGZfc2luZ2xlY2FzZXMgJT4lIG11dGF0ZShzeW1wX3JlbmFsX2FueSA9IGFwcGx5KGRmX3NpbmdsZWNhc2VzICU+JSBzZWxlY3Qoc3ltcF9yZW5hbF9BS0kpLCAxLCBhbnkpKQoKZGZfc2luZ2xlY2FzZXMgPC0gZGZfc2luZ2xlY2FzZXMgJT4lIG1vdmVtZSguLCAic3ltcF9yZW5hbF9hbnkgYmVmb3JlIHN5bXBfcmVuYWxfQUtJIikKYGBgCgpJZiBhbnkgY2FyZGlvdmFzY3VsYXIgc3ltcHRvbXMsIHN5bXBfY2FyZGlvdmFzY19hbnkgaXMgYW5ub3RhdGVkIGFzIFRSVUUuCgpgYGB7cn0KZGZfc2luZ2xlY2FzZXMgPC0gZGZfc2luZ2xlY2FzZXMgJT4lIG11dGF0ZShzeW1wX2NhcmRpb3Zhc2NfYW55ID0gYXBwbHkoZGZfc2luZ2xlY2FzZXMgJT4lIHNlbGVjdChzeW1wX2NhcmRpb3Zhc2NfbXlvY2FyZCwKc3ltcF9jYXJkaW92YXNjX3BlcmljYXJkLApzeW1wX2NhcmRpb3Zhc2NfY29yZGlsYXQsCnN5bXBfY2FyZGlvdmFzY19hbmV1cnlzbSwKc3ltcF9jYXJkaW92YXNjX3Nob2NrLApzeW1wX2NhcmRpb3Zhc2NfdGFjaHljYXJkLApzeW1wX2NhcmRpb3Zhc2NfYXJyaHl0KSwgMSwgYW55KSkKCmRmX3NpbmdsZWNhc2VzIDwtIGRmX3NpbmdsZWNhc2VzICU+JSBtb3ZlbWUoLiwgInN5bXBfY2FyZGlvdmFzY19hbnkgYmVmb3JlIHN5bXBfY2FyZGlvdmFzY19teW9jYXJkIikKCndyaXRlLmNzdihkZl9zaW5nbGVjYXNlcywgcGFzdGUwKCIuL2RhdGEvZGZfc2luZ2xlY2FzZXMuY3N2IikpCgojZGF0YXRhYmxlKGRmX3NpbmdsZWNhc2VzLCBjYXB0aW9uID0gIlNpbmdsZSBjYXNlcyBkYXRhZnJhbWUiKQpgYGAKCgo8YnV0dG9uIG9uY2xpY2s9ImxvY2F0aW9uLmhyZWY9J2h0dHBzOi8vZ2l0aHViLmNvbS9ybXZwYWVtZS9QSU1TX1RTL2Jsb2IvbWFzdGVyL2RhdGEvZGZfc2luZ2xlY2FzZXMuY3N2JyIgdHlwZT0iYnV0dG9uIj4KICAgICAgICAgRG93bmxvYWQgc2luZ2xlIGNhc2UgZGF0YSBhcyAuY3N2IG9uIEdpdGh1YjwvYnV0dG9uPgogICAgICAgICAKIyMgQ29ob3J0cwpBZnRlcndhcmRzLCB3ZSBkbyB0aGUgc2FtZSBmb3IgdGhlIGNvaG9ydCBzaGVldC4KClRoZSBwYXBlcnMgYnkgR3JpbWF1ZCBldCBhbC4gYW5kIFZlcmRvbmkgZXQgYWwuIGFyZSByZW1vdmVkIGZyb20gdGhlIGNvaG9ydCBkYXRhZnJhbWUsIGFzIG1vc3QgaW5mb3JtYXRpb24gaXMgcHJlc2VudCBpbiB0aGUgc2luZ2xlIGNhc2VzIGRhdGFmcmFtZS4gCmBgYHtyfQpkZl9jb2hvcnQgPC0KICByZWFkX2V4Y2VsKCIvVXNlcnMvcm12cGFlbWUvT25lZHJpdmUvVUdlbnQvUElNUy1UUyBTeXN0ZW1hdGljIFJldmlldyAtIERhdGEgZXh0cmFjdGllL2RhdGEgZXh0cmFjdGllLnhsc3giLAogICAgICAgICAgICAgc2hlZXQgPSAiQ29ob3J0cyIsCiAgICAgICAgICAgICBza2lwID0gMSwKICAgICAgICAgICAgIGNvbF9uYW1lcyA9IEZBTFNFKVssLWMoMTozKV0KCgpkZl9jb2hvcnQgPC0gZGZfY29ob3J0ICU+JSB0KCkKZGZfY29ob3J0IDwtIGFzLmRhdGEuZnJhbWUoZGZfY29ob3J0LCBzdHJpbmdzQXNGYWN0b3JzID0gRkFMU0UpCm5tcyA8LSBhcy52ZWN0b3IoZGZfY29ob3J0WzEsXSkKbm1zW2lzLm5hKG5tcyldIDwtICd0bXAnCmNvbG5hbWVzKGRmX2NvaG9ydCkgPC0gbWFrZS51bmlxdWUoYXMuY2hhcmFjdGVyKG5tcykpCmRmX2NvaG9ydCA8LSBkZl9jb2hvcnRbLTEsXQpkZl9jb2hvcnQgPC0gZGZfY29ob3J0ICU+JSBzZWxlY3QoLWNvbnRhaW5zKCJ0bXAiKSkKZGZfY29ob3J0IDwtIGRmX2NvaG9ydCAlPiUgc2VsZWN0KC12YXJpYWJsZV9pZCkKCmRmX2NvaG9ydCA8LSBkZl9jb2hvcnQgJT4lIAogIG11dGF0ZV9hbGwoZnVucyhzdHJfcmVwbGFjZSguLCAiWWVzIiwgInllcyIpKSkKZGZfY29ob3J0IDwtIGRmX2NvaG9ydCAlPiUgCiAgbXV0YXRlX2FsbChmdW5zKHN0cl9yZXBsYWNlKC4sICJObyIsICJubyIpKSkKZGZfY29ob3J0IDwtIGRmX2NvaG9ydCAlPiUgCiAgbXV0YXRlX2FsbChmdW5zKHN0cl9yZXBsYWNlKC4sICJwb3MiLCAieWVzIikpKQpkZl9jb2hvcnQgPC0gZGZfY29ob3J0ICU+JSAKICBtdXRhdGVfYWxsKGZ1bnMoc3RyX3JlcGxhY2UoLiwgIm5lZyIsICJubyIpKSkKCmRmX2NvaG9ydCA8LSBkZl9jb2hvcnQgJT4lCiAgcmVwbGFjZV93aXRoX25hX2FsbChjb25kaXRpb24gPSB+LnggPT0gIk5BIikKCmRmX2NvaG9ydCA8LSB0eXBlX2NvbnZlcnQoZGZfY29ob3J0KQoKZGZfY29ob3J0IDwtIGRmX2NvaG9ydFtjb2xTdW1zKCFpcy5uYShkZl9jb2hvcnQpKSA+IDBdCgpkZl9jb2hvcnQgPC0gZGZfY29ob3J0ICU+JSBmaWx0ZXIoZG9pICE9ICJodHRwczovL2RvaS5vcmcvMTAuMTE4Ni9zMTM2MTMtMDIwLTAwNjkwLTgiKSAlPiUgZmlsdGVyKGRvaSAhPSAiaHR0cHM6Ly9kb2kub3JnLzEwLjEwMTYvUzAxNDAtNjczNigyMCkzMTEwMy1YIikKCmRmX2NvaG9ydF9jb250cm9scyA8LSBkZl9jb2hvcnQKCmRmX2NvaG9ydCA8LSBkZl9jb2hvcnQgJT4lIGZpbHRlcihjb2hvcnRfdHlwZSA9PSAiY292aWQiKQoKd3JpdGUuY3N2KGRmX2NvaG9ydCwgcGFzdGUwKCIuL2RhdGEvZGZfY29ob3J0LmNzdiIpKQoKI2RhdGF0YWJsZShkZl9jb2hvcnQsIGNhcHRpb24gPSAiQ29ob3J0IGRhdGFmcmFtZSIpCmBgYAoKPGJ1dHRvbiBvbmNsaWNrPSJsb2NhdGlvbi5ocmVmPSdodHRwczovL2dpdGh1Yi5jb20vcm12cGFlbWUvUElNU19UUy9ibG9iL21hc3Rlci9kYXRhL2RmX2NvaG9ydC5jc3YnIiB0eXBlPSJidXR0b24iPgogICAgICAgICBEb3dubG9hZCBjb2hvcnQgZGF0YSBhcyAuY3N2IG9uIEdpdGh1YjwvYnV0dG9uPgoKIyBEZXNjcmlwdGl2ZSBzdGF0aXN0aWNzIHsudGFic2V0fQojIyBHZW5lcmFsCgoKKipDbGljayBvbiB0aGUgYW55IG9mIHRoZSB0YWJzIGFib3ZlIHRvIHNlZSBkZXNjcmlwdGl2ZSBzdGF0aXN0aWNzIGZvciBldmVyeSB2YXJpYWJsZSoqICAgICAgCgoKCiMjIFNpbmdsZSBjYXNlcwoqKkhvdyB0byByZWFkKiogIApVbmRlciAiVmFyaWFibGUgdHlwZTogbG9naWNhbCIsIHRoZSBudW1iZXIgb2YgdHJ1ZS9mYWxzZXMgYXJlIGRlcGljdGVkLiBFLmcuIGF0IHRoZSB0b3Agd2UgY2FuIHNlZSB0aGF0IHRoZXJlIGFyZSA5NSBudW1iZXIgb2Ygcm93cyAoPSA5NSBwYXRpZW50cykuIE92ZXJ3ZWlnaHQgaGFzIDc5IG1pc3NpbmcgdmFsdWVzICgxNyUgaXMgY29tcGxldGUpLCB3aGljaCBtZWFucyB0aGF0IDk1LTc5PTE2IHBhdGllbnRzIGhhdmUgZWl0aGVyICJUUlVFIiBvciAiRkFMU0UiIGZvciBvdmVyd2VpZ2h0LiBPZiB0aGVzZSAxNiwgOSBhcmUgbWFya2VkIGFzICJUUlVFIiBmb3Igb3ZlcndlaWdodC4gCgo8YnV0dG9uIG9uY2xpY2s9ImxvY2F0aW9uLmhyZWY9J2h0dHBzOi8vZ2l0aHViLmNvbS9ybXZwYWVtZS9QSU1TX1RTL2Jsb2IvbWFzdGVyL2RhdGEvc2luZ2xlY2FzZXNfZGVzY3JpcHRpdmVzdGF0cy5jc3YnIiB0eXBlPSJidXR0b24iPgogICAgICAgICBEb3dubG9hZCBkYXRhIGFzIC5jc3Ygb24gR2l0aHViPC9idXR0b24+CiAgICAgICAgIAoKYGBge3J9CiNza2ltKGRmX3NpbmdsZWNhc2VzKQp3cml0ZS5jc3Yoc2tpbShkZl9zaW5nbGVjYXNlcyksIHBhc3RlMCgiLi9kYXRhL3NpbmdsZWNhc2VzX2Rlc2NyaXB0aXZlc3RhdHMuY3N2IikpCmBgYAoKIyMgQ29ob3J0cwoqKkhvdyB0byByZWFkKiogIApUaGUgc3VtIGNvbHVtbiBlcXVhbHMgdGhlIHN1bSBvZiBhbGwgaW5kaXZpZHVhbHMsIGUuZy4gc3VtKHRvdF9jYXNlc19uKSBtZWFucyB0aGF0IHRoZXJlIGFyZSA1OTIgcGF0aWVudHMgaW4gdG90YWwgaW4gdGhlIGNvaG9ydHM7IHN1bShvdXRjb21lX2RlYXRoX24pIG1lYW5zIHRoYXQgOSBwYXRpZW50cyBkaWVkLiAKClRoZSAiUHJjdF90b3RhbCIgY29sdW1uIGlzIHRoZSBwZXJjZW50YWdlIG9mIGUuZy4gZGVhdGggKDkvNTkyKS4gT25seSBtYWtlcyBzZW5zZSB3aGVyZSBuIGlzIHJlcG9ydGVkIGUuZy4gdGhlcmFweSAobm90IGZvciBsYWIgdmFsdWVzKS4KCjxidXR0b24gb25jbGljaz0ibG9jYXRpb24uaHJlZj0naHR0cHM6Ly9naXRodWIuY29tL3JtdnBhZW1lL1BJTVNfVFMvYmxvYi9tYXN0ZXIvZGF0YS9jb2hvcnRfZGVzY3JpcHRpdmVzdGF0cy5jc3YnIiB0eXBlPSJidXR0b24iPgogICAgICAgICBEb3dubG9hZCBkYXRhIGFzIC5jc3Ygb24gR2l0aHViPC9idXR0b24+CgpgYGB7cn0Kc2tpbXN1bSA8LSBza2ltX3dpdGgobnVtZXJpYyA9IHNmbChzdW0gPSB+IHN1bSguLCBuYS5ybSA9IFRSVUUpLCBQcmN0X3RvdGFsID0gfiBzdW0oLiwgbmEucm0gPSBUUlVFKS9zdW0oZGZfY29ob3J0JHRvdF9jYXNlc19uKSoxMDApLCBhcHBlbmQgPSBUUlVFKQojc2tpbXN1bShkZl9jb2hvcnQpCndyaXRlLmNzdihza2ltc3VtKGRmX2NvaG9ydCksIHBhc3RlMCgiLi9kYXRhL2NvaG9ydF9kZXNjcmlwdGl2ZXN0YXRzLmNzdiIpKQpgYGAKCiMjIEhpc3RvcmljYWwgY29udHJvbHMKCjxidXR0b24gb25jbGljaz0ibG9jYXRpb24uaHJlZj0naHR0cHM6Ly9naXRodWIuY29tL3JtdnBhZW1lL1BJTVNfVFMvYmxvYi9tYXN0ZXIvZGF0YS9oaXN0b3JpY2FsY29udHJvbHNfZGVzY3JpcHRpdmVzdGF0cy5jc3YnIiB0eXBlPSJidXR0b24iPgogICAgICAgICBEb3dubG9hZCBkYXRhIGFzIC5jc3Ygb24gR2l0aHViPC9idXR0b24+CiAgICAgICAgIApgYGB7cn0KZGZfY29ob3J0X2NvbnRyb2xzX3N0YXRzIDwtIGRmX2NvaG9ydF9jb250cm9scyAlPiUgZmlsdGVyKGNvaG9ydF90eXBlID09ICJjb250cm9sIikKZGZfY29ob3J0X2NvbnRyb2xzX3N0YXRzIDwtIGRmX2NvaG9ydF9jb250cm9sc19zdGF0c1tjb2xTdW1zKCFpcy5uYShkZl9jb2hvcnRfY29udHJvbHNfc3RhdHMpKSA+IDBdCnNraW1zdW0gPC0gc2tpbV93aXRoKG51bWVyaWMgPSBzZmwoc3VtID0gfiBzdW0oLiwgbmEucm0gPSBUUlVFKSwgUHJjdF90b3RhbCA9IH4gc3VtKC4sIG5hLnJtID0gVFJVRSkvc3VtKGRmX2NvaG9ydF9jb250cm9sc19zdGF0cyR0b3RfY2FzZXNfbikqMTAwKSwgYXBwZW5kID0gVFJVRSkKI3NraW1zdW0oZGZfY29ob3J0X2NvbnRyb2xzX3N0YXRzKQoKd3JpdGUuY3N2KHNraW1zdW0oZGZfY29ob3J0X2NvbnRyb2xzX3N0YXRzKSwgcGFzdGUwKCIuL2RhdGEvaGlzdG9yaWNhbGNvbnRyb2xzX2Rlc2NyaXB0aXZlc3RhdHMuY3N2IikpCgp3cml0ZS5jc3YoZGZfY29ob3J0X2NvbnRyb2xzX3N0YXRzLCBwYXN0ZTAoIi4vZGF0YS9kZl9jb2hvcnRfY29udHJvbHNfc3RhdHMuY3N2IikpCmBgYAoKCiMgRGF0YSBleHBsb3JhdGlvbgojIyBUb3RhbCBjYXNlcyBhbmQgZGVhdGhzCmBgYHtyfQojdmFyX2lkX2NvaG9ydCA9ICJvdXRjb21lX2RlYXRoX24iCiN2YXJfaWRfc2luZ2xlID0gIm91dGNvbWVfZGVhdGgiCiN2YXJfaWQgPSAiZGVhdGhzIgptYWtlQmFycGxvdCgib3V0Y29tZV9kZWF0aF9uIiwgIm91dGNvbWVfZGVhdGgiLCAiZGVhdGhzIikKYGBgCgojIyBTZXgKYGBge3J9Cm5fY29ob3J0IDwtIGRmX2NvaG9ydCAlPiUgc2VsZWN0KHRvdF9jYXNlc19uKSAlPiUgc3VtKCkKdmFyX2NvaG9ydCA8LSBkZl9jb2hvcnQgJT4lIHNlbGVjdChjb250YWlucygic2V4IikpCnZhcl9jb2hvcnQgPC0gY29sU3Vtcyh2YXJfY29ob3J0LCBuYS5ybSA9IFRSVUUpCnZhcl9jb2hvcnQgPC0gdmFyX2NvaG9ydC9zdW0oZGZfY29ob3J0JHRvdF9jYXNlc19uKSoxMDAKdmFyX2NvaG9ydFsic2V4X25hIl0gPC0gKDEwMCAtIHZhcl9jb2hvcnRbInNleF9tIl0gLSB2YXJfY29ob3J0WyJzZXhfZiJdKQoKdmFyX2NvbnRyb2wgPC0gZGZfY29ob3J0X2NvbnRyb2xzICU+JSBmaWx0ZXIoY29ob3J0X2lkID09ICJQb3VsZXR0eSAtIGNvbnRyb2wiKSAlPiUgc2VsZWN0KGNvbnRhaW5zKCJzZXgiKSkKdmFyX2NvbnRyb2wgPC0gY29sU3Vtcyh2YXJfY29udHJvbCwgbmEucm0gPSBUUlVFKQp2YXJfY29udHJvbCA8LSB2YXJfY29udHJvbC9zdW0oZGZfY29ob3J0X2NvbnRyb2xzICU+JSBmaWx0ZXIoY29ob3J0X2lkID09ICJQb3VsZXR0eSAtIGNvbnRyb2wiKSAlPiUgc2VsZWN0KHRvdF9jYXNlc19uKSkqMTAwCnZhcl9jb250cm9sWyJzZXhfbmEiXSA8LSAoMTAwIC0gdmFyX2NvbnRyb2xbInNleF9tIl0gLSB2YXJfY29udHJvbFsic2V4X2YiXSkKCm5fc2luZ2xlIDwtIGRmX3NpbmdsZWNhc2VzICU+JSBucm93KCkKdmFyX3NpbmdsZSA8LSBkZl9zaW5nbGVjYXNlcyAlPiUgc2VsZWN0KGNvbnRhaW5zKCJzZXgiKSkKdmFyX3NpbmdsZSRzZXhfbSA8LSBpZmVsc2UodmFyX3NpbmdsZSRzZXggPT0gIk0iLCBUUlVFLCBGQUxTRSkKdmFyX3NpbmdsZSRzZXhfZiA8LSBpZmVsc2UodmFyX3NpbmdsZSRzZXggPT0gIkYiLCBUUlVFLCBGQUxTRSkKY29scyA8LSBzYXBwbHkodmFyX3NpbmdsZSwgaXMubG9naWNhbCkKdmFyX3NpbmdsZVssY29sc10gPC0gbGFwcGx5KHZhcl9zaW5nbGVbLGNvbHNdLCBhcy5udW1lcmljKQp2YXJfc2luZ2xlIDwtIGNvbFN1bXModmFyX3NpbmdsZSAlPiUgc2VsZWN0KC1zZXgpLCBuYS5ybSA9IFRSVUUpCnZhcl9zaW5nbGUgPC0gdmFyX3NpbmdsZS9ucm93KGRmX3NpbmdsZWNhc2VzKSoxMDAKdmFyX3NpbmdsZVsic2V4X25hIl0gPC0gKDEwMCAtIHZhcl9zaW5nbGVbInNleF9tIl0gLSB2YXJfc2luZ2xlWyJzZXhfZiJdKQoKYmFyX2RmX3ByY3QgPC0gZGF0YS5mcmFtZSgKICB4ID0gYygibWFsZXMiLCAiZmVtYWxlcyIsICJtaXNzaW5nIiwgIm1hbGVzIiwgImZlbWFsZXMiLCAibWlzc2luZyIsICJtYWxlcyIsICJmZW1hbGVzIiwgIm1pc3NpbmciKSwKICB2YWxzID0gYyh2YXJfc2luZ2xlLCB2YXJfY29ob3J0LCB2YXJfY29udHJvbCksCiAgY29sID0gYyhyZXAoInNpbmdsZSIsIGxlbmd0aCh2YXJfc2luZ2xlKSksIHJlcCgiY29ob3J0cyIsIGxlbmd0aCh2YXJfY29ob3J0KSksIHJlcCgiaGlzdG9yIGN0cmwiLCBsZW5ndGgodmFyX2NvbnRyb2wpKQopKQoKcF9wcmN0IDwtIGdncGxvdChiYXJfZGZfcHJjdCwgYWVzKHggPSBjb2wsIHkgPSAgdmFscywgZmlsbCA9IHgpKSArCiAgICBnZW9tX2JhcihzdGF0ID0gImlkZW50aXR5IiwgcG9zaXRpb24gPSAic3RhY2siKSArCiAgICB0aGVtZV9idygpICsgCiAgICBsYWJzKHRpdGxlID0gIk1hbGUvZmVtYWxlIGRpc3RyaWJ1dGlvbiBpbiBkYXRhc2V0Iiwgc3VidGl0bGUgPSAiUHJjdCIsIHggPSAic2V4IiwgeSA9ICIlIiwgY29sID0gIiAiKSAgKyBsaW1zKHkgPSBjKDAsMTAwKSkgKyB0aGVtZShheGlzLnRleHQueD1lbGVtZW50X3RleHQoYW5nbGU9OTAsIGhqdXN0PTEpKSsKICBzY2FsZV9maWxsX21hbnVhbCh2YWx1ZXMgPSB3ZXNfcGFsZXR0ZSgiUm95YWwxIikpCnBfcHJjdApgYGAKCgpgYGB7cn0KdmFyX2NvaG9ydCA8LSBkZl9jb2hvcnQgJT4lIHNlbGVjdChjb250YWlucygic2V4IikgfCAoImNvaG9ydF9pZCIpIHwgInRvdF9jYXNlc19uIikKc2V4X2YgPC0gdmFyX2NvaG9ydCAlPiUgZ3JvdXBfYnkoY29ob3J0X2lkKSAlPiUgc3VtbWFyaXplKHByY3QgPSBzZXhfZi90b3RfY2FzZXNfbikgJT4lICBtdXRhdGUoc2V4ID0gImZlbWFsZSIpCnNleF9tIDwtIHZhcl9jb2hvcnQgJT4lIGdyb3VwX2J5KGNvaG9ydF9pZCkgJT4lIHN1bW1hcml6ZShwcmN0ID0gc2V4X20vdG90X2Nhc2VzX24pICU+JSBtdXRhdGUoc2V4ID0gIm1hbGUiKQpzZXhfYWxsIDwtIHJiaW5kKHNleF9mLCBzZXhfbSkKCnBfc2V4X2NvaG9ydCA8LSBnZ3Bsb3Qoc2V4X2FsbCwgYWVzKHkgPSBjb2hvcnRfaWQsIHggPSBwcmN0LCBmaWxsID0gc2V4KSkgKyAKICAgICAgICAgIGdlb21fYmFyKHN0YXQgPSAiaWRlbnRpdHkiLCBwb3NpdGlvbiA9ICJmaWxsIikgKyAKICAgICAgICAgIHRoZW1lX2J3KCkgKyBsYWJzKHggPSAiIikgKyAKICAgICAgICAgIHNjYWxlX2ZpbGxfbWFudWFsKHZhbHVlcyA9IHdlc19wYWxldHRlKCJSb3lhbDEiKSkKCnZhcl9jb250cm9scyA8LSBkZl9jb2hvcnRfY29udHJvbHMgJT4lIGZpbHRlcihjb2hvcnRfaWQgPT0gIlBvdWxldHR5IC0gY29udHJvbCIpICU+JSBzZWxlY3QoY29udGFpbnMoInNleCIpIHwgKCJjb2hvcnRfaWQiKSB8ICJ0b3RfY2FzZXNfbiIpCnNleF9mIDwtIHZhcl9jb250cm9scyAlPiUgZ3JvdXBfYnkoY29ob3J0X2lkKSAlPiUgc3VtbWFyaXplKHByY3QgPSBzZXhfZi90b3RfY2FzZXNfbikgJT4lIG11dGF0ZShzZXggPSAiZmVtYWxlIikKc2V4X20gPC0gdmFyX2NvbnRyb2xzICU+JSBncm91cF9ieShjb2hvcnRfaWQpICU+JSBzdW1tYXJpemUocHJjdCA9IHNleF9tL3RvdF9jYXNlc19uKSAlPiUgbXV0YXRlKHNleCA9ICJtYWxlIikKc2V4X2FsbCA8LSByYmluZChzZXhfZiwgc2V4X20pCgpwX3NleF9jb250cm9scyA8LSBnZ3Bsb3Qoc2V4X2FsbCwgYWVzKHkgPSBjb2hvcnRfaWQsIHggPSBwcmN0LCBmaWxsID0gc2V4KSkgKyAKICAgICAgICAgIGdlb21fYmFyKHN0YXQgPSAiaWRlbnRpdHkiLCBwb3NpdGlvbiA9ICJmaWxsIikgKyAKICAgICAgICAgIHRoZW1lX2J3KCkgKyBsYWJzKHggPSAiIikgKyAKICAgICAgICAgIHNjYWxlX2ZpbGxfbWFudWFsKHZhbHVlcyA9IHdlc19wYWxldHRlKCJSb3lhbDEiKSkKCm5fc2luZ2xlIDwtIGRmX3NpbmdsZWNhc2VzICU+JSBucm93KCkKdmFyX3NpbmdsZSA8LSBkZl9zaW5nbGVjYXNlcyAlPiUgc2VsZWN0KGNvbnRhaW5zKCJzZXgiKSkKdmFyX3NpbmdsZSRzZXhfbSA8LSBpZmVsc2UodmFyX3NpbmdsZSRzZXggPT0gIk0iLCBUUlVFLCBGQUxTRSkKdmFyX3NpbmdsZSRzZXhfZiA8LSBpZmVsc2UodmFyX3NpbmdsZSRzZXggPT0gIkYiLCBUUlVFLCBGQUxTRSkKY29scyA8LSBzYXBwbHkodmFyX3NpbmdsZSwgaXMubG9naWNhbCkKdmFyX3NpbmdsZVssY29sc10gPC0gbGFwcGx5KHZhcl9zaW5nbGVbLGNvbHNdLCBhcy5udW1lcmljKQp2YXJfc2luZ2xlIDwtIGNvbFN1bXModmFyX3NpbmdsZSAlPiUgc2VsZWN0KC1zZXgpLCBuYS5ybSA9IFRSVUUpCnZhcl9zaW5nbGUgPC0gdmFyX3NpbmdsZS9ucm93KGRmX3NpbmdsZWNhc2VzKSoxMDAKCnNleF9zaW5nbGUgPC0gZGF0YS5mcmFtZShjb2hvcnRfaWQgPSAic2luZ2xlX2Nhc2VzIiwgcHJjdCA9IGModmFyX3NpbmdsZVsic2V4X20iXSwgdmFyX3NpbmdsZVsic2V4X2YiXSksIHNleCA9IGMoIm1hbGUiLCAiZmVtYWxlIikpCgpwX3NleF9zaW5nbGUgPC0gZ2dwbG90KHNleF9zaW5nbGUsIGFlcyh5ID0gY29ob3J0X2lkLCB4ID0gcHJjdCwgZmlsbCA9IHNleCkpICsgCiAgICAgICAgICBnZW9tX2JhcihzdGF0ID0gImlkZW50aXR5IiwgcG9zaXRpb24gPSAiZmlsbCIpICsgCiAgICAgICAgICB0aGVtZV9idygpICsgCiAgICAgICAgICBzY2FsZV9maWxsX21hbnVhbCh2YWx1ZXMgPSB3ZXNfcGFsZXR0ZSgiUm95YWwxIikpCgphIDwtIHBsb3RfZ3JpZChwX3NleF9jb2hvcnQsIHBfc2V4X2NvbnRyb2xzLCBwX3NleF9zaW5nbGUsIGFsaWduID0gInYiLCBucm93ID0gMywgcmVsX2hlaWdodHMgPSBjKDUvNywgMS83LCAxLzcpKQphCmBgYAoKIyMgQWdlIGRpc3RyaWJ1dGlvbgoKYGBge3J9CmNvaG9ydF9hZ2UgPC0gZGZfY29ob3J0X2NvbnRyb2xzICU+JSBzZWxlY3QoY29udGFpbnMoImNvaG9ydF9pZCIpIHwgY29udGFpbnMoImFnZSIpIHwgY29udGFpbnMoImNvaG9ydF90eXBlIikgIHwgY29udGFpbnMoInRvdF9jYXNlc19uIikpCmNvaG9ydF9hZ2UkY29ob3J0X2lkIDwtIHBhc3RlMChjb2hvcnRfYWdlJGNvaG9ydF9pZCwgIiAobiA9ICIsIGNvaG9ydF9hZ2UkdG90X2Nhc2VzX24sIikiKQpjb2hvcnRfYWdlJGFnZV9tZWRfeXJzIDwtIGFzLm51bWVyaWMoY29ob3J0X2FnZSRhZ2VfbWVkX3lycyApCmNvaG9ydF9hZ2UkYWdlX1ExX3lycyA8LSBhcy5udW1lcmljKGNvaG9ydF9hZ2UkYWdlX1ExX3lycykKY29ob3J0X2FnZSRhZ2VfUTNfeXJzIDwtIGFzLm51bWVyaWMoY29ob3J0X2FnZSRhZ2VfUTNfeXJzKQpjb2hvcnRfYWdlJGFnZV9taW5feXJzIDwtIGFzLm51bWVyaWMoY29ob3J0X2FnZSRhZ2VfbWluX3lycykKY29ob3J0X2FnZSRhZ2VfbWF4X3lycyA8LSBhcy5udW1lcmljKGNvaG9ydF9hZ2UkYWdlX21heF95cnMpCgpjb2hvcnRfYWdlJGRhdGFfZGVzY3IgPC0gaWZlbHNlKCFpcy5uYShjb2hvcnRfYWdlJGFnZV9RMV95cnMpICYgaXMubmEoY29ob3J0X2FnZSRhZ2VfbWluX3lycykgLCAiSVFSIiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWZlbHNlKGlzLm5hKGNvaG9ydF9hZ2UkYWdlX1ExX3lycykgJiAhaXMubmEoY29ob3J0X2FnZSRhZ2VfbWluX3lycyksICJyYW5nZSIsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZmVsc2UoIWlzLm5hKGNvaG9ydF9hZ2UkYWdlX1ExX3lycykgJiAhaXMubmEoY29ob3J0X2FnZSRhZ2VfbWluX3lycyksICJib3RoIiwgIm5vbmUiKSkpCgpwX2FnZV9jb2hvcnQgPC0gZ2dwbG90KGNvaG9ydF9hZ2UgJT4lIGZpbHRlcihjb2hvcnRfdHlwZSA9PSAiY292aWQiKSwgYWVzKHkgPSBjb2hvcnRfaWQsIHggPSBhZ2VfbWVkX3lycywgY29sID0gZGF0YV9kZXNjcikpICsgCiAgICAgICAgZ2VvbV9wb2ludChzaXplID0gNCkgKyAKICAgICAgICBnZW9tX2Vycm9yYmFyKGFlcyh4bWluPWFnZV9RMV95cnMsIHhtYXg9YWdlX1EzX3lycyksIHdpZHRoPS44LCBwb3NpdGlvbj1wb3NpdGlvbl9kb2RnZSguOSkpICsKICAgICAgICBnZW9tX2Vycm9yYmFyKGFlcyh4bWluPWFnZV9taW5feXJzLCAgeG1heD1hZ2VfbWF4X3lycyksIHdpZHRoPS4yLCBwb3NpdGlvbj1wb3NpdGlvbl9kb2RnZSguOSkpICsKICAgICAgICB0aGVtZV9idygpICsgbGltcyh4ID0gYygwLDIxKSkgKyAKICAgICAgICBsYWJzKHkgPSAiY29ob3J0IiwgeCA9ICIiLCBjb2wgPSAiYmFycyIpICsgdGhlbWUobGVnZW5kLnBvc2l0aW9uPSJ0b3AiKSsKICAgICAgICBzY2FsZV9jb2xvcl9tYW51YWwodmFsdWVzID0gYyh3ZXNfcGFsZXR0ZSgiQm90dGxlUm9ja2V0MiIpWzE6M10sIHdlc19wYWxldHRlKCJCb3R0bGVSb2NrZXQxIilbMl0pKQoKcF9hZ2VfY29udHJvbHMgPC0gZ2dwbG90KGNvaG9ydF9hZ2UgJT4lIGZpbHRlcihjb2hvcnRfdHlwZSAhPSAiY292aWQiKSwgYWVzKHkgPSBjb2hvcnRfaWQsIHggPSBhZ2VfbWVkX3lycywgY29sID0gZGF0YV9kZXNjcikpICsgCiAgICAgICAgZ2VvbV9wb2ludChzaXplID0gNCkgKyAKICAgICAgICBnZW9tX2Vycm9yYmFyKGFlcyh4bWluPWFnZV9RMV95cnMsIHhtYXg9YWdlX1EzX3lycyksIHdpZHRoPS4yLCBwb3NpdGlvbj1wb3NpdGlvbl9kb2RnZSguOSkpICsKICAgICAgICBnZW9tX2Vycm9yYmFyKGFlcyh4bWluPWFnZV9taW5feXJzLCAgeG1heD1hZ2VfbWF4X3lycyksIHdpZHRoPS4yLCBwb3NpdGlvbj1wb3NpdGlvbl9kb2RnZSguOSkpICsKICAgICAgICB0aGVtZV9idygpICsgbGltcyh4ID0gYygwLDIxKSkgKwogICAgICAgIGxhYnMoeSA9ICJjb2hvcnQiLCB4ID0gIiIsIGNvbCA9ICJiYXJzIikgKyB0aGVtZShsZWdlbmQucG9zaXRpb249Im5vbmUiKSsKICAgICAgICBzY2FsZV9jb2xvcl9tYW51YWwodmFsdWVzID0gd2VzX3BhbGV0dGUoIkJvdHRsZVJvY2tldDIiKVsyXSkKCnBfYWdlX3NpbmdsZSA8LSBnZ3Bsb3QoZGZfc2luZ2xlY2FzZXMsIGFlcyh4ID0gYXMubnVtZXJpYyhhZ2UpLCB5ID0gcGFzdGUwKCJzaW5nbGUgY2FzZXMgKG4gPSAiLCBuX3NpbmdsZSwiKSIpKSkgKwogICAgICBnZW9tX3Zpb2xpbihmaWxsID0gd2VzX3BhbGV0dGUoIkRhcmplZWxpbmcyIilbNF0pICsgCiAgICAgIGdlb21fYm94cGxvdCh3aWR0aD0uMywgZmlsbCA9IHdlc19wYWxldHRlKCJEYXJqZWVsaW5nMiIpWzFdKSArIAogICAgICB0aGVtZV9idygpICsgZ2VvbV9iZWVzd2FybShncm91cE9uWD1GQUxTRSwgYWxwaGEgPSAwLjUpICsgbGltcyh4ID0gYygwLDIxKSkgKyAKICAgICAgbGFicyh5ID0gImNvaG9ydCIsIHggPSAiQWdlICh5ZWFycykiKQoKYSA8LSBwbG90X2dyaWQocF9hZ2VfY29ob3J0LCBwX2FnZV9jb250cm9scywgcF9hZ2Vfc2luZ2xlLCBhbGlnbiA9ICJ2IiwgbnJvdyA9IDMsIHJlbF9oZWlnaHRzID0gYygyLzMsIDEvNSwgMS8zKSkKYQpgYGAKCgojIyBTeW1wdG9tcyAKIyMjIFNpbmdsZSBjYXNlcyB7LnRhYnNldH0KIyMjIyBBbGwgc3ltcHRvbXMKV2hlcmUgYXBwbGljYWJsZSwgb3ZlcmxhcCBvZiB2YXJpYWJsZSBpbiB0aGUgc2luZ2xlIGNhc2UgZ3JvdXAgd2FzIHN1bW1hcml6ZWQgd2l0aCBbVXBzZXQgcGxvdHMgKExleCAmIEdlaGxlbmJvcmcsIE5hdHVyZSBNZXRob2RzLCAyMDE0KV0oaHR0cHM6Ly93d3cubmF0dXJlLmNvbS9hcnRpY2xlcy9ubWV0aC4zMDMzKS4KCmBgYHtyfQptYWtlVXBzZXRSIDwtIGZ1bmN0aW9uKGlucHV0X2RmKXsKdmFyX3NpbmdsZSA8LSBpbnB1dF9kZiAKY29scyA8LSBzYXBwbHkodmFyX3NpbmdsZSwgaXMubG9naWNhbCkKdmFyX3NpbmdsZVssY29sc10gPC0gbGFwcGx5KHZhcl9zaW5nbGVbLGNvbHNdLCBhcy5udW1lcmljKQoKdmFyX3NpbmdsZV91cHNldHIgPC0gdmFyX3NpbmdsZSAKdmFyX3NpbmdsZV91cHNldHJbaXMubmEodmFyX3NpbmdsZV91cHNldHIpXSA8LSAwCnZhcl9zaW5nbGVfdXBzZXRyIDwtIGFzLmRhdGEuZnJhbWUodmFyX3NpbmdsZV91cHNldHIpCmZvcihpIGluIDE6bmNvbCh2YXJfc2luZ2xlX3Vwc2V0cikpeyB2YXJfc2luZ2xlX3Vwc2V0clsgLCBpXSA8LSBhcy5pbnRlZ2VyKHZhcl9zaW5nbGVfdXBzZXRyWyAsIGldKSB9CnVwc2V0KHZhcl9zaW5nbGVfdXBzZXRyLCBzZXRzID0gYyhjb2xuYW1lcyh2YXJfc2luZ2xlX3Vwc2V0cikpLCBzZXRzLmJhci5jb2xvciA9ICIjNTZCNEU5IiwKb3JkZXIuYnkgPSAiZnJlcSIsIGtlZXAub3JkZXIgPSBUUlVFKSMsIGVtcHR5LmludGVyc2VjdGlvbnMgPSAib24iLCBrZWVwLm9yZGVyID0gRkFMU0UpCn0KCm1ha2VVcHNldFIoZGZfc2luZ2xlY2FzZXMgJT4lIHNlbGVjdChjb250YWlucyggInN5bXAiKSkgJT4lIHNlbGVjdChjb250YWlucygiYW55IikpKQpgYGAKCiMjIyMgUmVzcGlyYXRvcnkKYGBge3J9Cm1ha2VVcHNldFIoZGZfc2luZ2xlY2FzZXMgJT4lIHNlbGVjdChjb250YWlucygic3ltcCIpKSAlPiUgc2VsZWN0KGNvbnRhaW5zKCJyZXNwIikpICU+JSBzZWxlY3QoLWNvbnRhaW5zKCJhbnkiKSkpCmBgYAoKIyMjIyBDYXJkaW92YXNjdWxhcgpgYGB7cn0KbWFrZVVwc2V0UihkZl9zaW5nbGVjYXNlcyAlPiUgc2VsZWN0KGNvbnRhaW5zKCJzeW1wIikpICU+JSBzZWxlY3QoY29udGFpbnMoImNhcmRpb3Zhc2MiKSkgJT4lIHNlbGVjdCgtY29udGFpbnMoIkxWRUYiKSkgJT4lIHNlbGVjdCgtY29udGFpbnMoImFueSIpKSkKYGBgCgojIyMjIEdJCmBgYHtyfQptYWtlVXBzZXRSKGRmX3NpbmdsZWNhc2VzICU+JSBzZWxlY3QoY29udGFpbnMoInN5bXAiKSkgJT4lIHNlbGVjdChjb250YWlucygiR0kiKSkgJT4lIHNlbGVjdCgtY29udGFpbnMoIm5ldXJvIikpICU+JSBzZWxlY3QoLWNvbnRhaW5zKCJhbnkiKSkpCmBgYAoKIyMjIFNpbmdsZSBjYXNlcyArIGNvaG9ydCB7LnRhYnNldH0KIyMjIyBSZXNwaXJhdG9yeQpgYGB7cn0KYmFyU3ltcCA8LSBmdW5jdGlvbihjb2xuYW1lX2Nob3J0LCBjb2xuYW1lX3NpbmdsZSwgZXhjbHVkZV9zaW5nbGUgPSBOVUxMLCBwbG90dGl0bGUpewoKdmFyX2NvaG9ydCA8LSBkZl9jb2hvcnQgJT4lIAogICAgICAgICAgICAgICAgICAgICAgICBzZWxlY3QoY29udGFpbnMoImNvaG9ydF9pZCIpIHwgY29udGFpbnMoInRvdF9jYXNlc19uIikgfCAoY29udGFpbnMoY29sbmFtZV9jaG9ydCkgJiBjb250YWlucygiX24iKSkpCgp2YXJfY29ob3J0IDwtIHZhcl9jb2hvcnQgJT4lIAogICAgICAgIGdhdGhlcih2YXJpYWJsZSwgdmFsdWUsIDM6bmNvbCh2YXJfY29ob3J0KSkgJT4lIAogICAgICAgIGRyb3BfbmEodmFsdWUpICAlPiUgZ3JvdXBfYnkodmFyaWFibGUpICU+JSAKICAgICAgICBzdW1tYXJpemUocHJjdCA9IHN1bSh2YWx1ZSkvc3VtKHRvdF9jYXNlc19uKSoxMDApCgp2YXJfY29ob3J0IDwtIHNldE5hbWVzKHZhcl9jb2hvcnQkcHJjdCwgdmFyX2NvaG9ydCR2YXJpYWJsZSkKbmFtZXModmFyX2NvaG9ydCkgPC0gc3ViKCJfbiIsICIiLCBuYW1lcyh2YXJfY29ob3J0KSkKCm5fc2luZ2xlIDwtIGRmX3NpbmdsZWNhc2VzICU+JSBucm93KCkKCmlmICghaXMubnVsbChleGNsdWRlX3NpbmdsZSkpewogIHZhcl9zaW5nbGUgPC0gZGZfc2luZ2xlY2FzZXMgJT4lIHNlbGVjdCgtY29udGFpbnMoZXhjbHVkZV9zaW5nbGUpKQogIHZhcl9zaW5nbGUgPC0gdmFyX3NpbmdsZSAlPiUgc2VsZWN0KGNvbnRhaW5zKGNvbG5hbWVfc2luZ2xlKSkKfSBlbHNlCnsKICB2YXJfc2luZ2xlIDwtIGRmX3NpbmdsZWNhc2VzICU+JSBzZWxlY3QoY29udGFpbnMoY29sbmFtZV9zaW5nbGUpKQp9CgogIyU+JSBzZWxlY3QoLWNvbnRhaW5zKCJhbnkiKSkKY29scyA8LSBzYXBwbHkodmFyX3NpbmdsZSwgaXMubG9naWNhbCkKdmFyX3NpbmdsZVssY29sc10gPC0gbGFwcGx5KHZhcl9zaW5nbGVbLGNvbHNdLCBhcy5udW1lcmljKQp2YXJfc2luZ2xlIDwtIGNvbFN1bXModmFyX3NpbmdsZSwgbmEucm0gPSBUUlVFKQp2YXJfc2luZ2xlIDwtIHZhcl9zaW5nbGUvbnJvdyhkZl9zaW5nbGVjYXNlcykqMTAwCgpiYXJfZGZfcHJjdCA8LSBkYXRhLmZyYW1lKAogIHggPSBjKG5hbWVzKHZhcl9zaW5nbGUpLCBuYW1lcyh2YXJfY29ob3J0KSksCiAgdmFscyA9IGModmFyX3NpbmdsZSwgdmFyX2NvaG9ydCksCiAgY29sID0gYyhyZXAoInNpbmdsZSIsIGxlbmd0aCh2YXJfc2luZ2xlKSksIHJlcCgiY29ob3J0cyIsIGxlbmd0aCh2YXJfY29ob3J0KSkpCikKCnBfcHJjdCA8LSBnZ3Bsb3QoYmFyX2RmX3ByY3QsIGFlcyh4ID0geCwgeSA9ICB2YWxzLCBmaWxsID0gY29sKSkgKwogICAgZ2VvbV9iYXIoc3RhdCA9ICJpZGVudGl0eSIsIHBvc2l0aW9uID0gImRvZGdlIikgKwogICAgdGhlbWVfYncoKSArIAogICAgbGFicyh0aXRsZSA9IHBsb3R0aXRsZSwgCiAgICAgICAgICBzdWJ0aXRsZSA9ICJQZXJjZW50IG9mIGdyb3VwIiwgeCA9ICJ0cmVhdG1lbnQiLCB5ID0gIiUiLCBjb2wgPSAiICIpICArIAogICAgICAgICAgdGhlbWUoYXhpcy50ZXh0Lng9ZWxlbWVudF90ZXh0KGFuZ2xlPTkwLCBoanVzdD0xKSkrCiAgICAgICAgICBzY2FsZV9maWxsX21hbnVhbCh2YWx1ZXMgPSB3ZXNfcGFsZXR0ZSgiUm95YWwxIikpCnBfcHJjdAp9CgptYWtlSGVhdG1hcF9jb2hvcnQoInN5bXBfcmVzcCIsICJzeW1wX3Jlc3AiLCBwbG90dGl0bGUgPSAiQ2FzZXMgd2l0aCByZXNwaXJhdG9yeSBzeW1wdG9tcywgcGVyIGNvaG9ydCIpCgpiYXJTeW1wKCJzeW1wX3Jlc3AiLCAic3ltcF9yZXNwIiwgcGxvdHRpdGxlID0gIkNhc2VzIHdpdGggcmVzcGlyYXRvcnkgc3ltcHRvbXMiKQpgYGAKCgpgYGB7cn0KIyB2YXJfY29ob3J0IDwtIGRmX2NvaG9ydCAlPiUgc2VsZWN0KCgiY29ob3J0X2lkIikgfCAidG90X2Nhc2VzX24iIHwoIGNvbnRhaW5zKCJzeW1wX3Jlc3AiKSAmIGNvbnRhaW5zKCJuIikpKQojIAojIHJlc3Bfc3ltcF9jb2hvcnQgPC0gdmFyX2NvaG9ydCAlPiUgCiMgICBnYXRoZXIodmFyaWFibGUsIHZhbHVlLCAzOm5jb2wodmFyX2NvaG9ydCkpICU+JSBncm91cF9ieShjb2hvcnRfaWQsIHZhcmlhYmxlKSAlPiUgc3VtbWFyaXplKHByY3QgPSB2YWx1ZS90b3RfY2FzZXNfbikKIyAKIyBnZ3Bsb3QocmVzcF9zeW1wX2NvaG9ydCwgYWVzKHggPSBwcmN0LCB5ID0gY29ob3J0X2lkLCBjb2wgPSB2YXJpYWJsZSkpICsgZ2VvbV9wb2ludCgpCmBgYAoKIyMjIyBDYXJkaW92YXNjdWxhcgpgYGB7cn0KbWFrZUhlYXRtYXBfY29ob3J0KCJzeW1wX2NhcmRpb3Zhc2MiLCAic3ltcF9jYXJkaW92YXNjIiwgZXhjbHVkZV9zaW5nbGUgPSAic3ltcF9jYXJkaW92YXNjX0xWRUYiLCBwbG90dGl0bGUgPSAiQ2FzZXMgd2l0aCBjYXJkaW92YXNjdWxhciBzeW1wdG9tcywgcGVyIGNvaG9ydCIpCgpiYXJTeW1wKCJzeW1wX2NhcmRpb3Zhc2MiLCAic3ltcF9jYXJkaW92YXNjIiwgZXhjbHVkZV9zaW5nbGUgPSAic3ltcF9jYXJkaW92YXNjX0xWRUYiLCBwbG90dGl0bGUgPSAiQ2FzZXMgd2l0aCBjYXJkaW92YXNjdWxhciBzeW1wdG9tcyIpCmBgYAoKIyMjIyBHYXN0cm8taW50ZXN0aW5hbApgYGB7cn0KbWFrZUhlYXRtYXBfY29ob3J0KCJzeW1wX0dJIiwgInN5bXBfR0kiLCBwbG90dGl0bGUgPSAiQ2FzZXMgd2l0aCBHSSBzeW1wdG9tcywgcGVyIGNvaG9ydCIpCgpiYXJTeW1wKCJzeW1wX0dJIiwgInN5bXBfR0kiLCBwbG90dGl0bGUgPSAiQ2FzZXMgd2l0aCBHSSBzeW1wdG9tcyIpCmBgYAoKIyMgQ09WSUQgY29udGFjdApgYGB7cn0KdmFyX2NvaG9ydCA8LSBkZl9jb2hvcnQgJT4lIHNlbGVjdCgoImNvaG9ydF9pZCIgfCAidG90X2Nhc2VzX24iKSB8ICggY29udGFpbnMoImNvdmlkIikgJiBjb250YWlucygiX24iKSAmIChjb250YWlucygicG9zIikgfCBjb250YWlucygiY2xvc2Vjb250IikgIHwgY29udGFpbnMoImFueSIpKSkpCnZhcl9jb2hvcnQkY29ob3J0X2lkIDwtIHBhc3RlMCh2YXJfY29ob3J0JGNvaG9ydF9pZCwgIiAobiA9ICIsIGFzLmNoYXJhY3Rlcih2YXJfY29ob3J0JHRvdF9jYXNlc19uKSwiKSIpCgp2YXJfY29ob3J0IDwtIHZhcl9jb2hvcnQgJT4lIAogIGdhdGhlcih2YXJpYWJsZSwgdmFsdWUsIDM6bmNvbCh2YXJfY29ob3J0KSkgJT4lIGdyb3VwX2J5KGNvaG9ydF9pZCwgdmFyaWFibGUpICU+JSBzdW1tYXJpemUocHJjdCA9IHZhbHVlL3RvdF9jYXNlc19uKjEwMCkKCnZhcl9jb2hvcnQkdmFyaWFibGUgPC0gc3ViKCJuXyIsICIiLCB2YXJfY29ob3J0JHZhcmlhYmxlKQoKdmFyX3NpbmdsZSA8LSBkZl9zaW5nbGVjYXNlcyAlPiUgc2VsZWN0KGNvbnRhaW5zKCJjb3ZpZCIpKQpjb2xzIDwtIHNhcHBseSh2YXJfc2luZ2xlLCBpcy5sb2dpY2FsKQp2YXJfc2luZ2xlWyxjb2xzXSA8LSBsYXBwbHkodmFyX3NpbmdsZVssY29sc10sIGFzLm51bWVyaWMpCnZhcl9zaW5nbGUgPC0gY29sU3Vtcyh2YXJfc2luZ2xlLCBuYS5ybSA9IFRSVUUpCnZhcl9zaW5nbGUgPC0gdmFyX3NpbmdsZS9ucm93KGRmX3NpbmdsZWNhc2VzKSoxMDAKdmFyX3NpbmdsZSA8LSBhcy5kYXRhLmZyYW1lKHZhcl9zaW5nbGUpICU+JSByb3duYW1lc190b19jb2x1bW4oKQp2YXJfc2luZ2xlJGNvaG9ydF9pZCA8LSBwYXN0ZTAoInNpbmdsZSBjYXNlcyAobiA9ICIsIG5fc2luZ2xlX2Nhc2VzLCIpIikKY29sbmFtZXModmFyX3NpbmdsZSkgPC0gYygidmFyaWFibGUiLCAicHJjdCIsICJjb2hvcnRfaWQiKQoKCm1pc3NpbmcgPC0gc2V0ZGlmZih2YXJfc2luZ2xlJHZhcmlhYmxlLCB2YXJfY29ob3J0JHZhcmlhYmxlKQppZiAobGVuZ3RoKG1pc3NpbmcpICE9IDAgKXsKICBtaXNzaW5nX2RmIDwtIGRhdGEuZnJhbWUodmFyaWFibGUgPSBtaXNzaW5nLCBwcmN0ID0gcmVwKE5BLCBsZW5ndGgobWlzc2luZykpLCBjb2hvcnRfaWQgPSByZXAodW5pcXVlKHZhcl9jb2hvcnQkY29ob3J0X2lkKSwgbGVuZ3RoKG1pc3NpbmcpKSkKICB2YXJfY29ob3J0IDwtIGJpbmRfcm93cyh2YXJfY29ob3J0LCBhc190aWJibGUobWlzc2luZ19kZikpCn0gCgptaXNzaW5nIDwtIHNldGRpZmYodmFyX2NvaG9ydCR2YXJpYWJsZSwgdmFyX3NpbmdsZSR2YXJpYWJsZSkKCmlmIChsZW5ndGgobWlzc2luZykgIT0gMCkgewogIGlmIChsZW5ndGgobWlzc2luZykgIT0gMCl7CmRhdGEuZnJhbWUodmFyaWFibGUgPSBtaXNzaW5nLCBwcmN0ID0gcmVwKE5BLCBsZW5ndGgobWlzc2luZykpLCBjb2hvcnRfaWQgPSByZXAodW5pcXVlKHZhcl9zaW5nbGUkY29ob3J0X2lkKSwgbGVuZ3RoKG1pc3NpbmcpKSkKICB2YXJfc2luZ2xlIDwtIGJpbmRfcm93cyh2YXJfc2luZ2xlLCBhc190aWJibGUobWlzc2luZ19kZikpCiAgfQp9CgoKaG1fY29ob3J0IDwtIGdncGxvdCh2YXJfY29ob3J0LCBhZXMoeCA9IHZhcmlhYmxlLCB5ID0gY29ob3J0X2lkLCBmaWxsID0gcHJjdCkpICsgCiAgICBnZW9tX3RpbGUoKSArIHRoZW1lX2NsYXNzaWMoKSArCiAgICB0aGVtZShheGlzLnRleHQueD1lbGVtZW50X2JsYW5rKCksIGF4aXMudGlja3MueD1lbGVtZW50X2JsYW5rKCksIGF4aXMubGluZT1lbGVtZW50X2JsYW5rKCkpKwogICBzY2FsZV9maWxsX2dyYWRpZW50KGxvdyA9ICJ5ZWxsb3ciLCBoaWdoPSJyZWQiLCBuYS52YWx1ZSA9ICJsaWdodGdyYXkiLCBsaW1pdHMgPSBjKDAsMTAwKSkgKwogICAgbGFicyh4ID0gIiIsIHkgPSAiY29ob3J0IiwgdGl0bGUgPSAiQ09WSUQgc3ltcHRvbXMsIHBlciBjb2hvcnQiKSArCiAgICBnZW9tX3RleHQoYWVzKGxhYmVsPXJvdW5kKHByY3QsIDIpKSwgc2l6ZSA9IDMsIGNvbG9yID0gImJsYWNrIikKCmhtX3NpbmdsZSA8LSBnZ3Bsb3QodmFyX3NpbmdsZSwgYWVzKHggPSB2YXJpYWJsZSwgeSA9IGNvaG9ydF9pZCwgZmlsbCA9IHByY3QpKSArIAogICAgZ2VvbV90aWxlKCkgKyAgdGhlbWVfY2xhc3NpYygpICsKICAgIHRoZW1lKGF4aXMudGV4dC54PWVsZW1lbnRfdGV4dChhbmdsZT05MCwgaGp1c3Q9MSksIGF4aXMubGluZT1lbGVtZW50X2JsYW5rKCkpKwogICAgc2NhbGVfZmlsbF9ncmFkaWVudChsb3cgPSAieWVsbG93IiwgaGlnaCA9ICJyZWQiLCBuYS52YWx1ZSA9ICJsaWdodGdyYXkiLCBsaW1pdHMgPSBjKDAsMTAwKSkrIGxhYnMoeSA9ICJjb2hvcnQiKSArCiAgICBnZW9tX3RleHQoYWVzKGxhYmVsPXJvdW5kKHByY3QsIDIpKSwgc2l6ZSA9IDMsIGNvbG9yID0gImJsYWNrIikgCgpwbG90X2dyaWQoaG1fY29ob3J0LCBobV9zaW5nbGUsIGFsaWduID0gInYiLCBucm93ID0gMiwgcmVsX2hlaWdodHMgPSBjKDEvMiwgMS8yKSkKCmBgYAoKYGBge3J9CnZhcl9jb2hvcnQgPC0gZGZfY29ob3J0ICU+JSAKICAgICAgICAgICAgICAgICAgICAgICAgc2VsZWN0KGNvbnRhaW5zKCJjb2hvcnRfaWQiKSB8IGNvbnRhaW5zKCJ0b3RfY2FzZXNfbiIpIHwgY29udGFpbnMoImNvdmlkIikgJiBjb250YWlucygiX24iKSAmIChjb250YWlucygiX3BvcyIpIHwgY29udGFpbnMoImNsb3NlIikpKQoKY292aWRfY29ob3J0IDwtIHZhcl9jb2hvcnQgJT4lIAogICAgICAgIGdhdGhlcih2YXJpYWJsZSwgdmFsdWUsIDM6bmNvbCh2YXJfY29ob3J0KSkgJT4lIAogICAgICAgIGRyb3BfbmEodmFsdWUpICAlPiUgZ3JvdXBfYnkodmFyaWFibGUpICU+JSAKICAgICAgICBzdW1tYXJpemUocHJjdCA9IHN1bSh2YWx1ZSkvc3VtKHRvdF9jYXNlc19uKSoxMDApCgpjb3ZpZF9jb2hvcnQgPC0gc2V0TmFtZXMoY292aWRfY29ob3J0JHByY3QsIGNvdmlkX2NvaG9ydCR2YXJpYWJsZSkKCm5fc2luZ2xlIDwtIGRmX3NpbmdsZWNhc2VzICU+JSBucm93KCkKdmFyX3NpbmdsZSA8LSBkZl9zaW5nbGVjYXNlcyAlPiUgc2VsZWN0KGNvbnRhaW5zKCJjb3ZpZCIpKSAKY29scyA8LSBzYXBwbHkodmFyX3NpbmdsZSwgaXMubG9naWNhbCkKdmFyX3NpbmdsZVssY29sc10gPC0gbGFwcGx5KHZhcl9zaW5nbGVbLGNvbHNdLCBhcy5udW1lcmljKQoKbWFrZVVwc2V0UihkZl9zaW5nbGVjYXNlcyAlPiUgc2VsZWN0KGNvbnRhaW5zKCJjb3ZpZCIpKSAlPiUgc2VsZWN0KC1jb250YWlucygiY292aWRfSWdNX3BvcyIpKSAlPiUgc2VsZWN0KC1jb250YWlucygiY292aWRfSWdBX3BvcyIpKSAgJT4lIHNlbGVjdCgtY29udGFpbnMoImNvdmlkX0lnR19wb3MiKSkgICU+JSBzZWxlY3QoLWNvbnRhaW5zKCJjb3ZpZF9zZXJvX3BvcyIpKSApCgp2YXJfc2luZ2xlIDwtIGNvbFN1bXModmFyX3NpbmdsZSwgbmEucm0gPSBUUlVFKQp2YXJfc2luZ2xlIDwtIHZhcl9zaW5nbGUvbnJvdyhkZl9zaW5nbGVjYXNlcykqMTAwCgpiYXJfZGZfcHJjdCA8LSBkYXRhLmZyYW1lKAogIHggPSBjKCJjbG9zZSBjb250YWN0IHJlcG9ydGVkIiwgIlBDUiArIiwgInN0b29sICsiLCJQQ1Igb3Igc3Rvb2wgb3Igc2VybyArIiwgImFueSBzZXJvbG9neSArIiwgInNlcm8gKyBmdXJ0aGVyIE5TIiwgIklnQSArIiwgIklnTSArIiwgIklnRyArIiwgImNsb3NlIGNvbnRhY3QgcmVwb3J0ZWQiLCAiSWdBICsiLCAiSWdHICsiLCAiSWdNICsiLCAiUENSICsiLCAic2VybyArIGZ1cnRoZXIgTlMiLCAic3Rvb2wgKyIpLAogIHZhbHMgPSBjKHZhcl9zaW5nbGUsIGNvdmlkX2NvaG9ydCksCiAgY29sID0gYyhyZXAoInNpbmdsZSIsIGxlbmd0aCh2YXJfc2luZ2xlKSksIHJlcCgiY29ob3J0cyIsIGxlbmd0aChjb3ZpZF9jb2hvcnQpKSkKKQoKcF9wcmN0IDwtIGdncGxvdChiYXJfZGZfcHJjdCwgYWVzKHggPSB4LCB5ID0gIHZhbHMsIGZpbGwgPSBjb2wpKSArCiAgICBnZW9tX2JhcihzdGF0ID0gImlkZW50aXR5IiwgcG9zaXRpb24gPSAiZG9kZ2UiKSArCiAgICB0aGVtZV9idygpICsgCiAgICBsYWJzKHRpdGxlID0gIlNBUlMtQ29WMiB0ZXN0aW5nIiwgCiAgICAgICAgIHN1YnRpdGxlID0gIlByY3QiLCB4ID0gInZhcmlhYmxlIiwgeSA9ICIlIiwgY29sID0gIiAiKSArCiAgICB0aGVtZShheGlzLnRleHQueD1lbGVtZW50X3RleHQoYW5nbGU9OTAsIGhqdXN0PTEpKSArCiAgICBzY2FsZV9maWxsX21hbnVhbCh2YWx1ZXMgPSB3ZXNfcGFsZXR0ZSgiUm95YWwxIikpCiNwX3ByY3QKCm5laXRoZXJfUENSX0lnIDwtIG5yb3coZGZfc2luZ2xlY2FzZXMgJT4lIGZpbHRlcigoY292aWRfc2Vyb19hbnkgPT0gRkFMU0UgfCBpcy5uYShjb3ZpZF9zZXJvX2FueSkpICYgKGNvdmlkX1BDUl9wb3MgPT0gRkFMU0UgfCBpcy5uYShjb3ZpZF9QQ1JfcG9zKSkgJiAoY292aWRfUENSX3N0b29sX3BvcyA9PSBGQUxTRSB8IGlzLm5hKGNvdmlkX1BDUl9zdG9vbF9wb3MpKSkpCgpuZWl0aGVyX1BDUl9JZ19jbG9zZWNvbnRhY3QgPC0KICBucm93KGRmX3NpbmdsZWNhc2VzICU+JSBmaWx0ZXIoKGNvdmlkX3Nlcm9fYW55ID09IEZBTFNFIHwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaXMubmEoY292aWRfc2Vyb19hbnkpKSAmCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKGNvdmlkX1BDUl9wb3MgPT0gRkFMU0UgfAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlzLm5hKGNvdmlkX1BDUl9wb3MpKSAmCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKGNvdmlkX1BDUl9zdG9vbF9wb3MgPT0gRkFMU0UgfAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlzLm5hKGNvdmlkX1BDUl9zdG9vbF9wb3MpKSAmCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKGNvdmlkX2Nsb3NlY29udGFjdCA9PSBGQUxTRSB8IGlzLm5hKGNvdmlkX2Nsb3NlY29udGFjdCkpCiAgKSkKCnByaW50KHBhc3RlMCgiQ2FzZXMgd2l0aCBuZWl0aGVyIFBDUiBub3Igc2Vyb2xvZ3k6ICIsIG5laXRoZXJfUENSX0lnKSkKCnByaW50KHBhc3RlMCgiQ2FzZXMgd2l0aCBuZWl0aGVyIFBDUiBub3Igc2Vyb2xvZ3kgbm9yIGNsb3NlY29udGFjdDogIiwgbmVpdGhlcl9QQ1JfSWdfY2xvc2Vjb250YWN0KSkKYGBgCgojIyBLYXdhc2FraSBjcml0ZXJpYQoKYGBge3J9Cm1ha2VIZWF0bWFwX2NvaG9ydCgia2F3YXNha2kiLCAia2F3YXNha2kiLGV4Y2x1ZGVfc2luZ2xlID0gImtveW9iYXMiLCBwbG90dGl0bGUgPSAiQ2FzZXMgd2l0aCBrYXdhc2FraSBzeW1wdG9tcywgcGVyIGNvaG9ydCIpCgpiYXJTeW1wKCJrYXdhc2FraSIsICJrYXdhc2FraSIsIGV4Y2x1ZGVfc2luZ2xlID0gImtveW9iYXMiLCBwbG90dGl0bGUgPSAiS2F3YXNha2kgc3ltcHRvbXMiKQpgYGAKCiMjIFNob2NrCmBgYHtyfQptYWtlQmFycGxvdCgic3ltcF9jYXJkaW92YXNjX3Nob2NrX24iLCAic3ltcF9jYXJkaW92YXNjX3Nob2NrIiwgIlNob2NrIikKYGBgCgojIyBMYWIgdmFsdWVzIHsudGFic2V0fQpGb3IgbGFiIHZhbHVlcywgc29tZXRpbWVzIG11bHRpcGxlIHZhbHVlcyBhcmUgcmVwb3J0ZWQgKGJhc2VsaW5lLCBwZWFrIG9yIG5vdC1zcGVjaWZpZWQpLiBBbGwgbGFiIHZhbHVlcyBhcmUgY29sbGFwc2VkIGJhc2VkIG9uIHRoZSBtYXggKG9yIHRoZSBtaW4gZm9yIGUuZy4gaGVtb2dsb2Jpbik6IHNvIG9ubHkgdGhlIGhpZ2hlc3QgdmFsdWUgb2YgbWVkaWFuLCBRMSBvciBRMyBpcyB1c2VkLiBEYXNoZWQgdmVydGljYWwgbGluZSBjb3JyZXNwb25kcyB0byB0aGUgY3V0b2ZmIHVzZWQgaW4gdGhlIHN0dWR5LiAKCiMjIyBDLXJlYWN0aXZlIHByb3RlaW4KCmBgYHtyfQpjcnBfY29sbGFwc2VfY29ob3J0IDwtIGNvbGxhcHNlX2xhYnZhbHNfY29ob3J0KGRmX2NvaG9ydF9jb250cm9scywgIm1heCIsICJDUlAiKQpjcnBfY29sbGFwc2Vfc2luZ2xlIDwtIGNvbGxhcHNlX2xhYnZhbHNfc2luZ2xlKGRmX3NpbmdsZWNhc2VzLCAibWF4IiwgIkNSUCIpCmNycF9taXNzaW5nIDwtIHN1bShpcy5uYShjcnBfY29sbGFwc2Vfc2luZ2xlJENSUF9tYXgpKQoKcF9jcnBfY29ob3J0IDwtIGdncGxvdChjcnBfY29sbGFwc2VfY29ob3J0LCBhZXMoeSA9IGNvaG9ydF9pZCwgeCA9IENSUF9tZWQsIGNvbCA9IGNvaG9ydF90eXBlKSkgKyAKICAgICAgICBnZW9tX3BvaW50KCkgKyAgCiAgICAgICAgZ2VvbV9lcnJvcmJhcihhZXMoeG1pbj1DUlBfbWluLCB4bWF4PUNSUF9tYXgpLCB3aWR0aD0uMiwgcG9zaXRpb249cG9zaXRpb25fZG9kZ2UoLjkpKSArIGxpbXMoeCA9IGMoMCw2MDApKSArIAogICAgICAgIHRoZW1lX2J3KCkgKyBsYWJzKHRpdGxlID0gIkNSUCIsIHkgPSAiY29ob3J0IiwgeCA9ICIiKSArCiAgICAgICAgZ2VvbV92bGluZSh4aW50ZXJjZXB0ID0gY29fQ1JQLCBsaW5ldHlwZSA9ICJkYXNoZWQiLCBjb2xvciA9ICJibGFjayIpICsgdGhlbWUobGVnZW5kLmp1c3RpZmljYXRpb24gPSBjKDEsIDEpLCBsZWdlbmQucG9zaXRpb24gPSBjKDAuOTgsIDAuOTgpLCBsZWdlbmQudGl0bGU9ZWxlbWVudF9ibGFuaygpKSArCiAgICAgICAgc2NhbGVfY29sb3JfbWFudWFsKHZhbHVlcyA9IHdlc19wYWxldHRlKCJSb3lhbDEiKSkKCnBfY3JwX3NpbmdsZSA8LSBnZ3Bsb3QoY3JwX2NvbGxhcHNlX3NpbmdsZSwgYWVzKHggPSBhcy5udW1lcmljKENSUF9tYXgpLCB5ID0gY29ob3J0X2lkKSkgKwogICAgICBnZW9tX3Zpb2xpbihmaWxsID0gd2VzX3BhbGV0dGUoIkRhcmplZWxpbmcyIilbNF0pICsgCiAgICAgIGdlb21fYm94cGxvdCh3aWR0aD0uMywgZmlsbCA9ICB3ZXNfcGFsZXR0ZSgiRGFyamVlbGluZzIiKVsxXSkgKyAKICAgICAgdGhlbWVfYncoKSArIGdlb21fYmVlc3dhcm0oZ3JvdXBPblg9RkFMU0UsIGFscGhhID0gMC41KSArIGxpbXMoeCA9IGMoMCw2MDApKSArIGxhYnMoeSA9ICIiLCB4ID0gIkNSUCAobWcvZEwpIiwgc3VidGl0bGUgPSBwYXN0ZTAoIm1pc3NpbmcgZGF0YSBmb3IgIiwgY3JwX21pc3NpbmcsICIgY2FzZXMiKSkgKwogICAgICBnZW9tX2hsaW5lKHlpbnRlcmNlcHQgPSBjb19DUlAsIGxpbmV0eXBlID0gImRhc2hlZCIsIGNvbG9yID0gImJsYWNrIikKCkNSUF9ncmlkIDwtIHBsb3RfZ3JpZChwX2NycF9jb2hvcnQsIHBfY3JwX3NpbmdsZSwgYWxpZ24gPSAidiIsIG5yb3cgPSAyLCByZWxfaGVpZ2h0cyA9IGMoMi8zLCAxLzMpKQpDUlBfZ3JpZApgYGAKCiMjIyBMeW1waG9jeXRlcwpgYGB7cn0KbHltcGhvX2NvbGxhcHNlX2NvaG9ydCA8LSBjb2xsYXBzZV9sYWJ2YWxzX2NvaG9ydChkZl9jb2hvcnRfY29udHJvbHMsICJtaW4iLCAibHltcGhvIikKbHltcGhvX2NvbGxhcHNlX3NpbmdsZSA8LSBjb2xsYXBzZV9sYWJ2YWxzX3NpbmdsZShkZl9zaW5nbGVjYXNlcywgIm1pbiIsICJseW1waG8iKQpseW1waG9fbWlzc2luZyA8LSBzdW0oaXMubmEobHltcGhvX2NvbGxhcHNlX3NpbmdsZSRseW1waG9fbWluKSkKCnBfbHltcGhvX2NvaG9ydCA8LSBnZ3Bsb3QobHltcGhvX2NvbGxhcHNlX2NvaG9ydCwgYWVzKHkgPSBjb2hvcnRfaWQsIHggPSBseW1waG9fbWVkLCBjb2wgPSBjb2hvcnRfdHlwZSkpICsgCiAgICAgICAgZ2VvbV9wb2ludCgpICsgIAogICAgICAgIGdlb21fZXJyb3JiYXIoYWVzKHhtaW49bHltcGhvX21pbiwgeG1heD1seW1waG9fbWF4KSwgd2lkdGg9LjIsIHBvc2l0aW9uPXBvc2l0aW9uX2RvZGdlKC45KSkgKyAKICAgICAgICB0aGVtZV9idygpICsgbGFicyh0aXRsZSA9ICJseW1waG9jeXRlcyIsIHkgPSAiIiwgeCA9ICIiKSArIGxpbXMoeCA9IGMoMCw3NTAwKSkgICsKICAgICAgICAgZ2VvbV92bGluZSh4aW50ZXJjZXB0ID0gY29fbHltcGhvLCBsaW5ldHlwZSA9ICJkYXNoZWQiLCBjb2xvciA9ICJibGFjayIpICsgdGhlbWUobGVnZW5kLmp1c3RpZmljYXRpb24gPSBjKDEsIDEpLCBsZWdlbmQucG9zaXRpb24gPSBjKDAuOTgsIDAuOTgpLCBsZWdlbmQudGl0bGU9ZWxlbWVudF9ibGFuaygpKSArCiAgICAgICAgc2NhbGVfY29sb3JfbWFudWFsKHZhbHVlcyA9IHdlc19wYWxldHRlKCJSb3lhbDEiKSkjKwogICAgICAgICNycmVtb3ZlKCJ5LnRleHQiKSAKCnBfbHltcGhvX3NpbmdsZSA8LSBnZ3Bsb3QobHltcGhvX2NvbGxhcHNlX3NpbmdsZSwgYWVzKHggPSBhcy5udW1lcmljKGx5bXBob19taW4pLCB5ID0gY29ob3J0X2lkKSkgKwogICAgICBnZW9tX3Zpb2xpbihmaWxsID0gd2VzX3BhbGV0dGUoIkRhcmplZWxpbmcyIilbNF0pICsgCiAgICAgIGdlb21fYm94cGxvdCh3aWR0aD0uMywgZmlsbCA9IHdlc19wYWxldHRlKCJEYXJqZWVsaW5nMiIpWzFdKSArIAogICAgICBsaW1zKHggPSBjKDAsNzUwMCkpKwogICAgICB0aGVtZV9idygpICsgZ2VvbV9iZWVzd2FybShncm91cE9uWD1GQUxTRSwgYWxwaGEgPSAwLjUpICArIGxhYnMoeSA9ICIiLCB4ID0gIkx5bXBob2N5dGVzICgvwrVMKSIsIHN1YnRpdGxlID0gcGFzdGUwKCJtaXNzaW5nIGRhdGEgZm9yICIsIGx5bXBob19taXNzaW5nLCAiIGNhc2VzIikpICsKICAgICAgZ2VvbV92bGluZSh4aW50ZXJjZXB0ID0gY29fbHltcGhvLCBsaW5ldHlwZSA9ICJkYXNoZWQiLCBjb2xvciA9ICJibGFjayIpICMrIAogICAgICAjcnJlbW92ZSgieS50ZXh0IikgCgpseW1waG9fZ3JpZCA8LSBwbG90X2dyaWQocF9seW1waG9fY29ob3J0LCBwX2x5bXBob19zaW5nbGUsIGFsaWduID0gInYiLCBucm93ID0gMiwgcmVsX2hlaWdodHMgPSBjKDIvMywgMS8zKSkKbHltcGhvX2dyaWQKYGBgCgojIyMgV2hpdGUgYmxvb2QgY2VsbHMKYGBge3J9CndiY19jb2xsYXBzZV9jb2hvcnQgPC0gY29sbGFwc2VfbGFidmFsc19jb2hvcnQoZGZfY29ob3J0X2NvbnRyb2xzLCAibWF4IiwgIldCQyIpCndiY19jb2xsYXBzZV9zaW5nbGUgPC0gY29sbGFwc2VfbGFidmFsc19zaW5nbGUoZGZfc2luZ2xlY2FzZXMsICJtYXgiLCAiV0JDIikKd2JjX21pc3NpbmcgPC0gc3VtKGlzLm5hKHdiY19jb2xsYXBzZV9zaW5nbGUkV0JDX21heCkpCgpwX3diY19jb2hvcnQgPC0gZ2dwbG90KHdiY19jb2xsYXBzZV9jb2hvcnQsIGFlcyh5ID0gY29ob3J0X2lkLCB4ID0gV0JDX21lZCwgY29sID0gY29ob3J0X3R5cGUpKSArIAogICAgICAgIGdlb21fcG9pbnQoKSArICAKICAgICAgICBnZW9tX2Vycm9yYmFyKGFlcyh4bWluPVdCQ19taW4sIHhtYXg9V0JDX21heCksIHdpZHRoPS4yLCBwb3NpdGlvbj1wb3NpdGlvbl9kb2RnZSguOSkpICsgbGltcyh4ID0gYygwLDUwMDAwKSkgKyAKICAgICAgICB0aGVtZV9idygpICsgbGFicyh0aXRsZSA9ICJXQkMiLCB5ID0gImNvaG9ydCIsIHggPSAiIikgICsKICAgICAgICBnZW9tX3ZsaW5lKHhpbnRlcmNlcHQgPSBjb19XQkMsIGxpbmV0eXBlID0gImRhc2hlZCIsIGNvbG9yID0gImJsYWNrIikgICsgdGhlbWUobGVnZW5kLmp1c3RpZmljYXRpb24gPSBjKDEsIDEpLCBsZWdlbmQucG9zaXRpb24gPSBjKDAuOTgsIDAuOTgpLCBsZWdlbmQudGl0bGU9ZWxlbWVudF9ibGFuaygpKSArCiAgICAgICAgc2NhbGVfY29sb3JfbWFudWFsKHZhbHVlcyA9IHdlc19wYWxldHRlKCJSb3lhbDEiKSkKCnBfd2JjX3NpbmdsZSA8LSBnZ3Bsb3Qod2JjX2NvbGxhcHNlX3NpbmdsZSwgYWVzKHggPSBhcy5udW1lcmljKFdCQ19tYXgpLCB5ID0gY29ob3J0X2lkKSkgKwogICAgICBnZW9tX3Zpb2xpbihmaWxsID0gd2VzX3BhbGV0dGUoIkRhcmplZWxpbmcyIilbNF0pICsgCiAgICAgIGdlb21fYm94cGxvdCh3aWR0aD0uMywgZmlsbCA9IHdlc19wYWxldHRlKCJEYXJqZWVsaW5nMiIpWzFdKSArIAogICAgICB0aGVtZV9idygpICsgZ2VvbV9iZWVzd2FybShncm91cE9uWD1GQUxTRSwgYWxwaGEgPSAwLjUpICsgbGFicyh5ID0gIiIsIHggPSAiV0JDICgvwrVMKSIsIHN1YnRpdGxlID0gcGFzdGUwKCJtaXNzaW5nIGRhdGEgZm9yICIsIHdiY19taXNzaW5nLCAiIGNhc2VzIikpICsgbGltcyh4ID0gYygwLDUwMDAwKSkgKwogICAgICBnZW9tX3ZsaW5lKHhpbnRlcmNlcHQgPSBjb19XQkMsIGxpbmV0eXBlID0gImRhc2hlZCIsIGNvbG9yID0gImJsYWNrIikgCgpXQkNfZ3JpZCA8LSBwbG90X2dyaWQocF93YmNfY29ob3J0LCBwX3diY19zaW5nbGUsIGFsaWduID0gInYiLCBucm93ID0gMiwgcmVsX2hlaWdodHMgPSBjKDIvMywgMS8zKSkKV0JDX2dyaWQKYGBgCgoKIyMjIEZlcnJpdGluCmBgYHtyfQpmZXJyaXRpbl9jb2xsYXBzZV9jb2hvcnQgPC0gY29sbGFwc2VfbGFidmFsc19jb2hvcnQoZGZfY29ob3J0X2NvbnRyb2xzLCAibWF4IiwgImZlcnJpdCIpCmZlcnJpdGluX2NvbGxhcHNlX3NpbmdsZSA8LSBjb2xsYXBzZV9sYWJ2YWxzX3NpbmdsZShkZl9zaW5nbGVjYXNlcywgIm1heCIsICJmZXJyaXQiKQpmZXJyaXRpbl9taXNzaW5nIDwtIHN1bShpcy5uYShmZXJyaXRpbl9jb2xsYXBzZV9zaW5nbGUkZmVycml0X21heCkpCgpwX2ZlcnJpdGluX2NvaG9ydCA8LSBnZ3Bsb3QoZmVycml0aW5fY29sbGFwc2VfY29ob3J0LCBhZXMoeSA9IGNvaG9ydF9pZCwgeCA9IGZlcnJpdF9tZWQsIGNvbCA9IGNvaG9ydF90eXBlKSkgKyAKICAgICAgICBnZW9tX3BvaW50KCkgKyAgCiAgICAgICAgZ2VvbV9lcnJvcmJhcihhZXMoeG1pbj1mZXJyaXRfbWluLCB4bWF4PWZlcnJpdF9tYXgpLCB3aWR0aD0uMiwgcG9zaXRpb249cG9zaXRpb25fZG9kZ2UoLjkpKSArIGxpbXMoeCA9IGMoMCwxMTAwMCkpICsgCiAgICAgICAgdGhlbWVfYncoKSArIGxhYnModGl0bGUgPSAiRmVycml0aW4iLCB5ID0gImNvaG9ydCIsIHggPSAiIikgKwogICAgICAgIGdlb21fdmxpbmUoeGludGVyY2VwdCA9IGNvX2ZlcnJpdGluLCBsaW5ldHlwZSA9ICJkYXNoZWQiLCBjb2xvciA9ICJibGFjayIpICsgdGhlbWUobGVnZW5kLmp1c3RpZmljYXRpb24gPSBjKDEsIDEpLCBsZWdlbmQucG9zaXRpb24gPSBjKDAuOTgsIDAuOTgpLCBsZWdlbmQudGl0bGU9ZWxlbWVudF9ibGFuaygpKSArCiAgICAgICAgc2NhbGVfY29sb3JfbWFudWFsKHZhbHVlcyA9IHdlc19wYWxldHRlKCJSb3lhbDEiKSkKCnBfZmVycml0aW5fc2luZ2xlIDwtIGdncGxvdChmZXJyaXRpbl9jb2xsYXBzZV9zaW5nbGUsIGFlcyh4ID0gYXMubnVtZXJpYyhmZXJyaXRfbWF4KSwgeSA9IGNvaG9ydF9pZCkpICsKICAgICAgZ2VvbV92aW9saW4oZmlsbCA9IHdlc19wYWxldHRlKCJEYXJqZWVsaW5nMiIpWzRdKSArIAogICAgICBnZW9tX2JveHBsb3Qod2lkdGg9LjMsIGZpbGwgPSB3ZXNfcGFsZXR0ZSgiRGFyamVlbGluZzIiKVsxXSkgKyAKICAgICAgdGhlbWVfYncoKSArIGdlb21fYmVlc3dhcm0oZ3JvdXBPblg9RkFMU0UsIGFscGhhID0gMC41KSArIGxhYnMoeSA9ICIiLCB4ID0gIkZlcnJpdGluICjCtWcvbCkiLCBzdWJ0aXRsZSA9IHBhc3RlMCgibWlzc2luZyBkYXRhIGZvciAiLCBmZXJyaXRpbl9taXNzaW5nLCAiIGNhc2VzIikpICsgbGltcyh4ID0gYygwLDExMDAwKSkgKwogICAgICBnZW9tX3ZsaW5lKHhpbnRlcmNlcHQgPSBjb19mZXJyaXRpbiwgbGluZXR5cGUgPSAiZGFzaGVkIiwgY29sb3IgPSAiYmxhY2siKSAKCmZlcnJpdGluX2dyaWQgPC0gcGxvdF9ncmlkKHBfZmVycml0aW5fY29ob3J0LCBwX2ZlcnJpdGluX3NpbmdsZSwgYWxpZ24gPSAidiIsIG5yb3cgPSAyLCByZWxfaGVpZ2h0cyA9IGMoMi8zLCAxLzMpKQpmZXJyaXRpbl9ncmlkCmBgYAoKCiMjIyBUcm9wb25pbgpgYGB7cn0KdHJvcG9uaW5fY29sbGFwc2VfY29ob3J0IDwtIGNvbGxhcHNlX2xhYnZhbHNfY29ob3J0KGRmX2NvaG9ydF9jb250cm9scywgIm1heCIsICJ0cm9wb25pbiIpCnRyb3BvbmluX2NvbGxhcHNlX3NpbmdsZSA8LSBjb2xsYXBzZV9sYWJ2YWxzX3NpbmdsZShkZl9zaW5nbGVjYXNlcywgIm1heCIsICJ0cm9wb25pbiIpCnRyb3BvbmluX21pc3NpbmcgPC0gc3VtKGlzLm5hKHRyb3BvbmluX2NvbGxhcHNlX3NpbmdsZSR0cm9wb25pbl9tYXgpKQoKcF90cm9wb25pbl9jb2hvcnQgPC0gZ2dwbG90KHRyb3BvbmluX2NvbGxhcHNlX2NvaG9ydCwgYWVzKHkgPSBjb2hvcnRfaWQsIHggPSB0cm9wb25pbl9tZWQsIGNvbCA9IGNvaG9ydF90eXBlKSkgKyAKICAgICAgICBnZW9tX3BvaW50KCkgKyAgCiAgICAgICAgZ2VvbV9lcnJvcmJhcihhZXMoeG1pbj10cm9wb25pbl9taW4sIHhtYXg9dHJvcG9uaW5fbWF4KSwgd2lkdGg9LjIsIHBvc2l0aW9uPXBvc2l0aW9uX2RvZGdlKC45KSkgKyBsaW1zKHggPSBjKDAsNzAwMCkpICsgCiAgICAgICAgdGhlbWVfYncoKSArIGxhYnModGl0bGUgPSAiVHJvcG9uaW4iLCB5ID0gImNvaG9ydCIsIHggPSAiIikgICsKICAgICAgICBnZW9tX3ZsaW5lKHhpbnRlcmNlcHQgPSBjb190cm9wbywgbGluZXR5cGUgPSAiZGFzaGVkIiwgY29sb3IgPSAiYmxhY2siKSAgKyB0aGVtZShsZWdlbmQuanVzdGlmaWNhdGlvbiA9IGMoMSwgMSksIGxlZ2VuZC5wb3NpdGlvbiA9IGMoMC45OCwgMC45OCksIGxlZ2VuZC50aXRsZT1lbGVtZW50X2JsYW5rKCkpICsKICAgICAgICBzY2FsZV9jb2xvcl9tYW51YWwodmFsdWVzID0gd2VzX3BhbGV0dGUoIlJveWFsMSIpKQoKcF90cm9wb25pbl9zaW5nbGUgPC0gZ2dwbG90KHRyb3BvbmluX2NvbGxhcHNlX3NpbmdsZSwgYWVzKHggPSBhcy5udW1lcmljKHRyb3BvbmluX21heCksIHkgPSBjb2hvcnRfaWQpKSArCiAgICAgIGdlb21fdmlvbGluKGZpbGwgPSB3ZXNfcGFsZXR0ZSgiRGFyamVlbGluZzIiKVs0XSkgKyAKICAgICAgZ2VvbV9ib3hwbG90KHdpZHRoPS4zLCBmaWxsID0gd2VzX3BhbGV0dGUoIkRhcmplZWxpbmcyIilbMV0pICsgCiAgICAgIHRoZW1lX2J3KCkgKyBnZW9tX2JlZXN3YXJtKGdyb3VwT25YPUZBTFNFLCBhbHBoYSA9IDAuNSkgKyBsYWJzKHkgPSAiIiwgeCA9ICJUcm9wb25pbiAobmcvTCkiLCBzdWJ0aXRsZSA9IHBhc3RlMCgibWlzc2luZyBkYXRhIGZvciAiLCB0cm9wb25pbl9taXNzaW5nLCAiIGNhc2VzIikpICsgbGltcyh4ID0gYygwLDcwMDApKSArCiAgICAgIGdlb21fdmxpbmUoeGludGVyY2VwdCA9IGNvX3Ryb3BvLCBsaW5ldHlwZSA9ICJkYXNoZWQiLCBjb2xvciA9ICJibGFjayIpIAoKdHJvcG9uaW5fZ3JpZCA8LSBwbG90X2dyaWQocF90cm9wb25pbl9jb2hvcnQsIHBfdHJvcG9uaW5fc2luZ2xlLCBhbGlnbiA9ICJ2IiwgbnJvdyA9IDIsIHJlbF9oZWlnaHRzID0gYygyLzMsIDEvMykpCnRyb3BvbmluX2dyaWQKYGBgCgoKIyMjIElMLTYKTm90ZTogVGhlIGNhc2VzIGZyb20gUG91bGV0dHkgZXQgYWwgYXJlIGFkZGVkIHRvIHRoZSBzaW5nbGUgY2FzZXMgYXMgdGhleSByZXBvcnQgb24gSUw2IHZhbHVlcy4gCgpgYGB7cn0KSUw2X2NvbGxhcHNlX2NvaG9ydCA8LSBjb2xsYXBzZV9sYWJ2YWxzX2NvaG9ydChkZl9jb2hvcnRfY29udHJvbHMsICJtYXgiLCAiSUw2IikKSUw2X2NvbGxhcHNlX3NpbmdsZSA8LSBjb2xsYXBzZV9sYWJ2YWxzX3NpbmdsZShkZl9zaW5nbGVjYXNlc19pbmNsUG91bGV0dHksICJtYXgiLCAiSUw2IikKSUw2X21pc3NpbmcgPC0gc3VtKGlzLm5hKElMNl9jb2xsYXBzZV9zaW5nbGUkSUw2X21heCkpCgpwX0lMNl9jb2hvcnQgPC0gZ2dwbG90KElMNl9jb2xsYXBzZV9jb2hvcnQsIGFlcyh5ID0gY29ob3J0X2lkLCB4ID0gSUw2X21lZCkpICsgCiAgICAgICAgZ2VvbV9wb2ludCgpICsgIAogICAgICAgIGdlb21fZXJyb3JiYXIoYWVzKHhtaW49SUw2X21pbiwgeG1heD1JTDZfbWF4KSwgd2lkdGg9LjIsIHBvc2l0aW9uPXBvc2l0aW9uX2RvZGdlKC45KSkgKyBsaW1zKHggPSBjKDAsMjUwMCkpICsgCiAgICAgICAgdGhlbWVfYncoKSArIGxhYnModGl0bGUgPSAiSUw2IiwgeSA9ICJjb2hvcnQiLCB4ID0gIiIpICArCiAgICAgICAgZ2VvbV92bGluZSh4aW50ZXJjZXB0ID0gY29fSUw2LCBsaW5ldHlwZSA9ICJkYXNoZWQiLCBjb2xvciA9ICJibGFjayIpICArCiAgICAgICAgc2NhbGVfY29sb3JfbWFudWFsKHZhbHVlcyA9IHdlc19wYWxldHRlKCJSb3lhbDEiKSkKCnBfSUw2X3NpbmdsZSA8LSBnZ3Bsb3QoSUw2X2NvbGxhcHNlX3NpbmdsZSwgYWVzKHggPSBhcy5udW1lcmljKElMNl9tYXgpLCB5ID0gY29ob3J0X2lkKSkgKwogICAgICBnZW9tX3Zpb2xpbihmaWxsID0gd2VzX3BhbGV0dGUoIkRhcmplZWxpbmcyIilbNF0pICsgCiAgICAgIGdlb21fYm94cGxvdCh3aWR0aD0uMywgZmlsbCA9IHdlc19wYWxldHRlKCJEYXJqZWVsaW5nMiIpWzFdKSArIAogICAgICB0aGVtZV9idygpICsgZ2VvbV9iZWVzd2FybShncm91cE9uWD1GQUxTRSwgYWxwaGEgPSAwLjUpICsgbGFicyh5ID0gIiIsIHggPSAiSUw2IChwZy9tbCkiLCBzdWJ0aXRsZSA9IHBhc3RlMCgibWlzc2luZyBkYXRhIGZvciAiLCBJTDZfbWlzc2luZywgIiBjYXNlcyIpKSArIGxpbXMoeCA9IGMoMCwyNTAwKSkgKwogICAgICBnZW9tX3ZsaW5lKHhpbnRlcmNlcHQgPSBjb19JTDYsIGxpbmV0eXBlID0gImRhc2hlZCIsIGNvbG9yID0gImJsYWNrIikgCgpJTDZfZ3JpZCA8LSBwbG90X2dyaWQocF9JTDZfY29ob3J0LCBwX0lMNl9zaW5nbGUsIGFsaWduID0gInYiLCBucm93ID0gMiwgcmVsX2hlaWdodHMgPSBjKDIvMywgMS8zKSkKSUw2X2dyaWQKYGBgCgoKIyMjIEJOUAoKYGBge3J9CmNvbGxhcHNlX2NvaG9ydCA8LSBjb2xsYXBzZV9sYWJ2YWxzX2NvaG9ydChkZl9jb2hvcnRfY29udHJvbHMsICJtYXgiLCAiX0JOUCIpCmNvbGxhcHNlX3NpbmdsZSA8LSBjb2xsYXBzZV9sYWJ2YWxzX3NpbmdsZShkZl9zaW5nbGVjYXNlcywgIm1heCIsICJfQk5QIikKbWlzc2luZyA8LSBzdW0oaXMubmEoY29sbGFwc2Vfc2luZ2xlJGBfQk5QX21heGApKQoKcF9CTlBfY29ob3J0IDwtIGdncGxvdChjb2xsYXBzZV9jb2hvcnQsIGFlcyh5ID0gY29ob3J0X2lkLCB4ID0gYF9CTlBfbWVkYCwgY29sID0gY29ob3J0X3R5cGUpKSArIAogICAgICAgIGdlb21fcG9pbnQoKSArICAKICAgICAgICBnZW9tX2Vycm9yYmFyKGFlcyh4bWluPWBfQk5QX21pbmAsIHhtYXg9YF9CTlBfbWF4YCksIHdpZHRoPS4yLCBwb3NpdGlvbj1wb3NpdGlvbl9kb2RnZSguOSkpICsgbGltcyh4ID0gYygwLDIwMDAwKSkgKyAKICAgICAgICB0aGVtZV9idygpICsgbGFicyh0aXRsZSA9ICJCTlAiLCB5ID0gImNvaG9ydCIsIHggPSAiIikgICsKICAgICAgICBnZW9tX3ZsaW5lKHhpbnRlcmNlcHQgPSBjb19CTlAsIGxpbmV0eXBlID0gImRhc2hlZCIsIGNvbG9yID0gImJsYWNrIikgICt0aGVtZShsZWdlbmQuanVzdGlmaWNhdGlvbiA9IGMoMSwgMSksIGxlZ2VuZC5wb3NpdGlvbiA9IGMoMC45OCwgMC45OCkpICsKICAgICAgICBzY2FsZV9jb2xvcl9tYW51YWwodmFsdWVzID0gd2VzX3BhbGV0dGUoIlJveWFsMSIpKQoKcF9CTlBfc2luZ2xlIDwtIGdncGxvdChjb2xsYXBzZV9zaW5nbGUsIGFlcyh4ID0gYXMubnVtZXJpYyhgX0JOUF9tYXhgKSwgeSA9IGNvaG9ydF9pZCkpICsKICAgICAgZ2VvbV92aW9saW4oZmlsbCA9IHdlc19wYWxldHRlKCJEYXJqZWVsaW5nMiIpWzRdKSArIAogICAgICBnZW9tX2JveHBsb3Qod2lkdGg9LjMsIGZpbGwgPSB3ZXNfcGFsZXR0ZSgiRGFyamVlbGluZzIiKVsxXSkgKyAKICAgICAgdGhlbWVfYncoKSArIGdlb21fYmVlc3dhcm0oZ3JvdXBPblg9RkFMU0UsIGFscGhhID0gMC41KSArIGxhYnMoeSA9ICIiLCB4ID0gIkJOUCAocGcvbWwpIiwgc3VidGl0bGUgPSBwYXN0ZTAoIm1pc3NpbmcgZGF0YSBmb3IgIiwgbWlzc2luZywgIiBjYXNlcyIpKSArIGxpbXMoeCA9IGMoMCwyMDAwMCkpICsKICAgICAgZ2VvbV92bGluZSh4aW50ZXJjZXB0ID0gY29fQk5QLCBsaW5ldHlwZSA9ICJkYXNoZWQiLCBjb2xvciA9ICJibGFjayIpIAoKQk5QX2dyaWQgPC0gcGxvdF9ncmlkKHBfQk5QX2NvaG9ydCwgcF9CTlBfc2luZ2xlLCBhbGlnbiA9ICJ2IiwgbnJvdyA9IDIsIHJlbF9oZWlnaHRzID0gYygyLzMsIDEvMykpCkJOUF9ncmlkCmBgYAoKIyMjIE5UcHJvQk5QCmBgYHtyfQpjb2xsYXBzZV9jb2hvcnQgPC0gY29sbGFwc2VfbGFidmFsc19jb2hvcnQoZGZfY29ob3J0X2NvbnRyb2xzLCAibWF4IiwgIk5UcHJvQk5QIikKY29sbGFwc2Vfc2luZ2xlIDwtIGNvbGxhcHNlX2xhYnZhbHNfc2luZ2xlKGRmX3NpbmdsZWNhc2VzLCAibWF4IiwgIk5UcHJvQk5QIikKbWlzc2luZyA8LSBzdW0oaXMubmEoY29sbGFwc2Vfc2luZ2xlJE5UcHJvQk5QX21heCkpCgpwX05UcHJvQk5QX2NvaG9ydCA8LSBnZ3Bsb3QoY29sbGFwc2VfY29ob3J0LCBhZXMoeSA9IGNvaG9ydF9pZCwgeCA9IE5UcHJvQk5QX21lZCwgY29sID0gY29ob3J0X3R5cGUpKSArIAogICAgICAgIGdlb21fcG9pbnQoKSArICAKICAgICAgICBnZW9tX2Vycm9yYmFyKGFlcyh4bWluPU5UcHJvQk5QX21pbiwgeG1heD1OVHByb0JOUF9tYXgpLCB3aWR0aD0uMiwgcG9zaXRpb249cG9zaXRpb25fZG9kZ2UoLjkpKSArIGxpbXMoeCA9IGMoMCw3MDAwMCkpICsgCiAgICAgICAgdGhlbWVfYncoKSArIGxhYnModGl0bGUgPSAiTlRwcm9CTlAiLCB5ID0gImNvaG9ydCIsIHggPSAiIikgICsKICAgICAgICBnZW9tX3ZsaW5lKHhpbnRlcmNlcHQgPSBjb19OVHByb0JOUCwgbGluZXR5cGUgPSAiZGFzaGVkIiwgY29sb3IgPSAiYmxhY2siKSArIHRoZW1lKGxlZ2VuZC5qdXN0aWZpY2F0aW9uID0gYygxLCAxKSwgbGVnZW5kLnBvc2l0aW9uID0gYygwLjk4LCAwLjk4KSwgbGVnZW5kLnRpdGxlPWVsZW1lbnRfYmxhbmsoKSkgKwogICAgICAgIHNjYWxlX2NvbG9yX21hbnVhbCh2YWx1ZXMgPSB3ZXNfcGFsZXR0ZSgiUm95YWwxIikpCgpwX05UcHJvQk5QX3NpbmdsZSA8LSBnZ3Bsb3QoY29sbGFwc2Vfc2luZ2xlLCBhZXMoeCA9IGFzLm51bWVyaWMoTlRwcm9CTlBfbWF4KSwgeSA9IGNvaG9ydF9pZCkpICsKICAgICAgZ2VvbV92aW9saW4oZmlsbCA9IHdlc19wYWxldHRlKCJEYXJqZWVsaW5nMiIpWzRdKSArIAogICAgICBnZW9tX2JveHBsb3Qod2lkdGg9LjMsIGZpbGwgPSB3ZXNfcGFsZXR0ZSgiRGFyamVlbGluZzIiKVsxXSkgKyAKICAgICAgdGhlbWVfYncoKSArIGdlb21fYmVlc3dhcm0oZ3JvdXBPblg9RkFMU0UsIGFscGhhID0gMC41KSArIGxhYnMoeSA9ICIiLCB4ID0gIk5UcHJvQk5QIChwZy9tbCkiLCBzdWJ0aXRsZSA9IHBhc3RlMCgibWlzc2luZyBkYXRhIGZvciAiLCBtaXNzaW5nLCAiIGNhc2VzIikpICsgbGltcyh4ID0gYygwLDcwMDAwKSkgKwogICAgICBnZW9tX3ZsaW5lKHhpbnRlcmNlcHQgPSBjb19OVHByb0JOUCwgbGluZXR5cGUgPSAiZGFzaGVkIiwgY29sb3IgPSAiYmxhY2siKSAKCk5UcHJvQk5QX2dyaWQgPC0gcGxvdF9ncmlkKHBfTlRwcm9CTlBfY29ob3J0LCBwX05UcHJvQk5QX3NpbmdsZSwgYWxpZ24gPSAidiIsIG5yb3cgPSAyLCByZWxfaGVpZ2h0cyA9IGMoMi8zLCAxLzMpKQpOVHByb0JOUF9ncmlkCmBgYAoKCiMjIyBQbGF0ZWxldHMKCmBgYHtyfQpjb2xsYXBzZV9jb2hvcnQgPC0gY29sbGFwc2VfbGFidmFsc19jb2hvcnQoZGZfY29ob3J0X2NvbnRyb2xzLCAibWluIiwgInBsYXRlbGV0IikKY29sbGFwc2Vfc2luZ2xlIDwtIGNvbGxhcHNlX2xhYnZhbHNfc2luZ2xlKGRmX3NpbmdsZWNhc2VzLCAibWluIiwgInBsYXRlbGV0IikKbWlzc2luZyA8LSBzdW0oaXMubmEoY29sbGFwc2Vfc2luZ2xlJHBsYXRlbGV0X21pbikpCgpwX3BsYXRlbGV0X2NvaG9ydCA8LSBnZ3Bsb3QoY29sbGFwc2VfY29ob3J0LCBhZXMoeSA9IGNvaG9ydF9pZCwgeCA9IHBsYXRlbGV0X21lZCwgY29sID0gY29ob3J0X3R5cGUpKSArIAogICAgICAgIGdlb21fcG9pbnQoKSArICAKICAgICAgICBnZW9tX2Vycm9yYmFyKGFlcyh4bWluPXBsYXRlbGV0X21pbiwgeG1heD1wbGF0ZWxldF9tYXgsIGNvbD1jb2hvcnRfdHlwZSksIHdpZHRoPS4yLCBwb3NpdGlvbj1wb3NpdGlvbl9kb2RnZSguOSkpICsgbGltcyh4ID0gYygwLDc1MDAwMCkpICsgCiAgICAgICAgdGhlbWVfYncoKSArIGxhYnModGl0bGUgPSAicGxhdGVsZXQiLCB5ID0gImNvaG9ydCIsIHggPSAiIikgICsKICAgICAgICBnZW9tX3ZsaW5lKHhpbnRlcmNlcHQgPSBjb19wbGF0ZWxldCwgbGluZXR5cGUgPSAiZGFzaGVkIiwgY29sb3IgPSAiYmxhY2siKSAgKyB0aGVtZShsZWdlbmQuanVzdGlmaWNhdGlvbiA9IGMoMSwgMSksIGxlZ2VuZC5wb3NpdGlvbiA9IGMoMC45OCwgMC45OCksIGxlZ2VuZC50aXRsZT1lbGVtZW50X2JsYW5rKCkpICsKICAgICAgICBzY2FsZV9jb2xvcl9tYW51YWwodmFsdWVzID0gd2VzX3BhbGV0dGUoIlJveWFsMSIpKQoKcF9wbGF0ZWxldF9zaW5nbGUgPC0gZ2dwbG90KGNvbGxhcHNlX3NpbmdsZSwgYWVzKHggPSBhcy5udW1lcmljKHBsYXRlbGV0X21pbiksIHkgPSBjb2hvcnRfaWQpKSArCiAgICAgIGdlb21fdmlvbGluKGZpbGwgPSB3ZXNfcGFsZXR0ZSgiRGFyamVlbGluZzIiKVs0XSkgKyAKICAgICAgZ2VvbV9ib3hwbG90KHdpZHRoPS4zLCBmaWxsID0gd2VzX3BhbGV0dGUoIkRhcmplZWxpbmcyIilbMV0pICsgCiAgICAgIHRoZW1lX2J3KCkgKyBnZW9tX2JlZXN3YXJtKGdyb3VwT25YPUZBTFNFLCBhbHBoYSA9IDAuNSkgKyBsYWJzKHkgPSAiIiwgeCA9ICJQbGF0ZWxldHMgKC/CtUwpIiwgc3VidGl0bGUgPSBwYXN0ZTAoIm1pc3NpbmcgZGF0YSBmb3IgIiwgbWlzc2luZywgIiBjYXNlcyIpKSArIGxpbXMoeCA9IGMoMCw3NTAwMDApKSArCiAgICAgIGdlb21fdmxpbmUoeGludGVyY2VwdCA9IGNvX3BsYXRlbGV0LCBsaW5ldHlwZSA9ICJkYXNoZWQiLCBjb2xvciA9ICJibGFjayIpIAoKcGxhdGVsZXRfZ3JpZCA8LSBwbG90X2dyaWQocF9wbGF0ZWxldF9jb2hvcnQsIHBfcGxhdGVsZXRfc2luZ2xlLCBhbGlnbiA9ICJ2IiwgbnJvdyA9IDIsIHJlbF9oZWlnaHRzID0gYygyLzMsIDEvMykpCnBsYXRlbGV0X2dyaWQKYGBgCgoKIyMjIEQtZGltZXJzCgpgYGB7cn0KY29sbGFwc2VfY29ob3J0IDwtIGNvbGxhcHNlX2xhYnZhbHNfY29ob3J0KGRmX2NvaG9ydF9jb250cm9scywgIm1heCIsICJEZGltIikKY29sbGFwc2Vfc2luZ2xlIDwtIGNvbGxhcHNlX2xhYnZhbHNfc2luZ2xlKGRmX3NpbmdsZWNhc2VzLCAibWF4IiwgIkRkaW0iKQptaXNzaW5nIDwtIHN1bShpcy5uYShjb2xsYXBzZV9zaW5nbGUkRGRpbV9tYXgpKQoKcF9EZGltX2NvaG9ydCA8LSBnZ3Bsb3QoY29sbGFwc2VfY29ob3J0LCBhZXMoeSA9IGNvaG9ydF9pZCwgeCA9IERkaW1fbWVkLCBjb2wgPSBjb2hvcnRfdHlwZSkpICsgCiAgICAgICAgZ2VvbV9wb2ludCgpICsgIAogICAgICAgIGdlb21fZXJyb3JiYXIoYWVzKHhtaW49RGRpbV9taW4sIHhtYXg9RGRpbV9tYXgsIGNvbD1jb2hvcnRfdHlwZSksIHdpZHRoPS4yLCBwb3NpdGlvbj1wb3NpdGlvbl9kb2RnZSguOSkpICsgbGltcyh4ID0gYygwLDExMDAwKSkgKyAKICAgICAgICB0aGVtZV9idygpICsgbGFicyh0aXRsZSA9ICJELWRpbWVycyIsIHkgPSAiY29ob3J0IiwgeCA9ICIiKSAgKwogICAgICAgIGdlb21fdmxpbmUoeGludGVyY2VwdCA9IGNvX0RkaW0sIGxpbmV0eXBlID0gImRhc2hlZCIsIGNvbG9yID0gImJsYWNrIikgICsgdGhlbWUobGVnZW5kLmp1c3RpZmljYXRpb24gPSBjKDEsIDEpLCBsZWdlbmQucG9zaXRpb24gPSBjKDAuOTgsIDAuOTgpLCBsZWdlbmQudGl0bGU9ZWxlbWVudF9ibGFuaygpKSArCiAgICAgICAgc2NhbGVfY29sb3JfbWFudWFsKHZhbHVlcyA9IHdlc19wYWxldHRlKCJSb3lhbDEiKSkKCnBfRGRpbV9zaW5nbGUgPC0gZ2dwbG90KGNvbGxhcHNlX3NpbmdsZSwgYWVzKHggPSBhcy5udW1lcmljKERkaW1fbWF4KSwgeSA9IGNvaG9ydF9pZCkpICsKICAgICAgZ2VvbV92aW9saW4oZmlsbCA9IHdlc19wYWxldHRlKCJEYXJqZWVsaW5nMiIpWzRdKSArIAogICAgICBnZW9tX2JveHBsb3Qod2lkdGg9LjMsIGZpbGwgPSB3ZXNfcGFsZXR0ZSgiRGFyamVlbGluZzIiKVsxXSkgKyAKICAgICAgdGhlbWVfYncoKSArIGdlb21fYmVlc3dhcm0oZ3JvdXBPblg9RkFMU0UsIGFscGhhID0gMC41KSArIGxhYnMoeSA9ICIiLCB4ID0gIkQtZGltZXJzIChuZy9tbCkiLCBzdWJ0aXRsZSA9IHBhc3RlMCgibWlzc2luZyBkYXRhIGZvciAiLCBtaXNzaW5nLCAiIGNhc2VzIikpICsgbGltcyh4ID0gYygwLDExMDAwKSkgKwogICAgICBnZW9tX3ZsaW5lKHhpbnRlcmNlcHQgPSBjb19EZGltLCBsaW5ldHlwZSA9ICJkYXNoZWQiLCBjb2xvciA9ICJibGFjayIpIAoKRGRpbV9ncmlkIDwtIHBsb3RfZ3JpZChwX0RkaW1fY29ob3J0LCBwX0RkaW1fc2luZ2xlLCBhbGlnbiA9ICJ2IiwgbnJvdyA9IDIsIHJlbF9oZWlnaHRzID0gYygyLzMsIDEvMykpCkRkaW1fZ3JpZApgYGAKCgojIyMgU29kaXVtCgpgYGB7cn0KY29sbGFwc2VfY29ob3J0IDwtIGNvbGxhcHNlX2xhYnZhbHNfY29ob3J0KGRmX2NvaG9ydF9jb250cm9scywgIm1pbiIsICJzb2RpdW0iKQpjb2xsYXBzZV9zaW5nbGUgPC0gY29sbGFwc2VfbGFidmFsc19zaW5nbGUoZGZfc2luZ2xlY2FzZXMsICJtaW4iLCAic29kaXVtIikKbWlzc2luZyA8LSBzdW0oaXMubmEoY29sbGFwc2Vfc2luZ2xlJHNvZGl1bV9taW4pKQoKcF9zb2RpdW1fY29ob3J0IDwtIGdncGxvdChjb2xsYXBzZV9jb2hvcnQsIGFlcyh5ID0gY29ob3J0X2lkLCB4ID0gc29kaXVtX21lZCwgY29sID0gY29ob3J0X3R5cGUpKSArIAogICAgICAgIGdlb21fcG9pbnQoKSArICAKICAgICAgICBnZW9tX2Vycm9yYmFyKGFlcyh4bWluPXNvZGl1bV9taW4sIHhtYXg9c29kaXVtX21heCwgY29sPWNvaG9ydF90eXBlKSwgd2lkdGg9LjIsIHBvc2l0aW9uPXBvc2l0aW9uX2RvZGdlKC45KSkgKyBsaW1zKHggPSBjKDEwMCwyMDApKSArIAogICAgICAgIHRoZW1lX2J3KCkgKyBsYWJzKHRpdGxlID0gIlNvZGl1bSIsIHkgPSAiY29ob3J0IiwgeCA9ICIiKSAgKwogICAgICAgIGdlb21fdmxpbmUoeGludGVyY2VwdCA9IGNvX3NvZGl1bSwgbGluZXR5cGUgPSAiZGFzaGVkIiwgY29sb3IgPSAiYmxhY2siKSAgKyB0aGVtZShsZWdlbmQuanVzdGlmaWNhdGlvbiA9IGMoMSwgMSksIGxlZ2VuZC5wb3NpdGlvbiA9IGMoMC45OCwgMC45OCksIGxlZ2VuZC50aXRsZT1lbGVtZW50X2JsYW5rKCkpICsKICAgICAgICBzY2FsZV9jb2xvcl9tYW51YWwodmFsdWVzID0gd2VzX3BhbGV0dGUoIlJveWFsMSIpKQoKcF9zb2RpdW1fc2luZ2xlIDwtIGdncGxvdChjb2xsYXBzZV9zaW5nbGUsIGFlcyh4ID0gYXMubnVtZXJpYyhzb2RpdW1fbWluKSwgeSA9IGNvaG9ydF9pZCkpICsKICAgICAgZ2VvbV92aW9saW4oZmlsbCA9IHdlc19wYWxldHRlKCJEYXJqZWVsaW5nMiIpWzRdKSArIAogICAgICBnZW9tX2JveHBsb3Qod2lkdGg9LjMsIGZpbGwgPSB3ZXNfcGFsZXR0ZSgiRGFyamVlbGluZzIiKVsxXSkgKyAKICAgICAgdGhlbWVfYncoKSArIGdlb21fYmVlc3dhcm0oZ3JvdXBPblg9RkFMU0UsIGFscGhhID0gMC41KSArIGxhYnMoeSA9ICIiLCB4ID0gIlNvZGl1bSAobW1vbC9MKSIsIHN1YnRpdGxlID0gcGFzdGUwKCJtaXNzaW5nIGRhdGEgZm9yICIsIG1pc3NpbmcsICIgY2FzZXMiKSkgKyBsaW1zKHggPSBjKDEwMCwyMDApKSArCiAgICAgIGdlb21fdmxpbmUoeGludGVyY2VwdCA9IGNvX3NvZGl1bSwgbGluZXR5cGUgPSAiZGFzaGVkIiwgY29sb3IgPSAiYmxhY2siKSAKCnNvZGl1bV9ncmlkIDwtIHBsb3RfZ3JpZChwX3NvZGl1bV9jb2hvcnQsIHBfc29kaXVtX3NpbmdsZSwgYWxpZ24gPSAidiIsIG5yb3cgPSAyLCByZWxfaGVpZ2h0cyA9IGMoMi8zLCAxLzMpKQpzb2RpdW1fZ3JpZApgYGAKCgojIyBDcml0aWNhbCBjYXJlIGludGVydmVudGlvbnMKCiMjIyBJbm90cm9wZXMKYGBge3J9Cm1ha2VCYXJwbG90KHZhcl9pZF9jb2hvcnQgPSAiY3JpdGNhcmVfaW5vdHJvcF9uIiwgdmFyX2lkX3NpbmdsZSA9ICJjcml0Y2FyZV9pbm90cm9wIiwgdmFyX2lkID0gImlub3Ryb3BlcyIpCmBgYAoKYGBge3J9Cm1ha2VIZWF0bWFwX2NvaG9ydCgiY3JpdGNhcmUiLCAiY3JpdGNhcmUiLGV4Y2x1ZGVfc2luZ2xlID0gImRheXMiLCBwbG90dGl0bGUgPSAiQ2FzZXMgcmVjZWl2aW5nIGNyaXRpY2FsIGNhcmUgaW50ZXJ2ZW50aW9ucywgcGVyIGNvaG9ydCIpCgpiYXJTeW1wKCJjcml0Y2FyZSIsICJjcml0Y2FyZSIsIGV4Y2x1ZGVfc2luZ2xlID0gImRheXMiLCBwbG90dGl0bGUgPSAiQ2FzZXMgcmVjZWl2aW5nIGNyaXRpY2FsIGNhcmUgaW50ZXJ2ZW50aW9ucyIpCmBgYAoKIyMgVHJlYXRtZW50cwojIyMgSVZJZwpgYGB7cn0KbWFrZUJhcnBsb3QodmFyX2lkX2NvaG9ydCA9ICJyeF9JVklnX29uY2VfbiIsIHZhcl9pZF9zaW5nbGUgPSAicnhfSVZJZ19vbmNlIiwgdmFyX2lkID0gIklWSWciKQpgYGAKCiMjIyBPdmVyYWxsIHRoZXJhcHkKYGBge3J9Cm1ha2VIZWF0bWFwX2NvaG9ydCgicngiLCAicngiLGV4Y2x1ZGVfc2luZ2xlID0gImRheXMiLCBwbG90dGl0bGUgPSAiQ2FzZXMgcmVjZWl2aW5nIHRyZWF0bWVudCwgcGVyIGNvaG9ydCIpCgoKYmFyU3ltcCgicngiLCAicngiLCBleGNsdWRlX3NpbmdsZSA9ICJkYXlzIiwgcGxvdHRpdGxlID0gIkNhc2VzIHJlY2VpdmluZyB0cmVhdG1lbnQiKQpgYGAKCgojIENhc2UgZGVmaW5pdGlvbnMgCiMjIExhYiByZWZlcmVuY2UgdmFsdWVzCkN1dC1vZmZzIGluIHRoaXMgc3R1ZHk6CgotIE5ldXRyb3BoaWxpYSA+IDgwMDAvwrVMCi0gRWxldmF0ZWQgQ1JQID4gMTAgbWcvTAotIEx5bXBob3BlbmlhIDwgMTI1MC/CtUwKLSBXQkMgPiAxMTAwMC/CtUwKLSBGaWJyaW5vZ2VuID4gNDAwIG1nL2RMCi0gRC1kaW1lcnMgPiAyNTAgbmcvbUwKLSBGZXJyaXRpbiA+IDMwMCBuZy9tTAotIEFsYnVtaW4gPCAzNCBnL0wKLSBQcm9jYWxjaXRvbmluID4gMC40OSBuZy9tTAotIExESCA+IDI4MCBVL0wKLSBJTDYgPiAxNi40IHBnL21MCi0gRVNSID4gMjIgbW0vCi0gQk5QID4gMTAwIHBnL21MCi0gTlRwcm9CTlAgPiA0MDAgcGcvbUwKLSBUcm9wb25pbiA+IDAuMDQgbmcvbUwKCiMjIFJDUENILCBDREMgYW5kIFdITyB7LnRhYnNldH0KCiMjIyBQSU1TLVRTCltTb3VyY2UgUkNQQ0hdKGh0dHBzOi8vd3d3LnJjcGNoLmFjLnVrL3NpdGVzL2RlZmF1bHQvZmlsZXMvMjAyMC0wNS9DT1ZJRC0xOS1QYWVkaWF0cmljLW11bHRpc3lzdGVtLSUyMGluZmxhbW1hdG9yeSUyMHN5bmRyb21lLTIwMjAwNTAxLnBkZikgIAoKMS4gQSBjaGlsZCBwcmVzZW50aW5nIHdpdGggcGVyc2lzdGVudCBmZXZlciwgaW5mbGFtbWF0aW9uIChuZXV0cm9waGlsaWEsIGVsZXZhdGVkIENSUCBhbmQgbHltcGhvcGFlbmlhKSBhbmQgZXZpZGVuY2Ugb2Ygc2luZ2xlIG9yIG11bHRpLW9yZ2FuIGR5c2Z1bmN0aW9uIChzaG9jaywgY2FyZGlhYywgcmVzcGlyYXRvcnksIHJlbmFsLCBnYXN0cm9pbnRlc3RpbmFsIG9yIG5ldXJvbG9naWNhbCBkaXNvcmRlcikgd2l0aCBhZGRpdGlvbmFsIGZlYXR1cmVzIChzZWUgbGlzdGVkIGluIEFwcGVuZGl4IDEgKS4gVGhpcyBtYXkgaW5jbHVkZSBjaGlsZHJlbiBmdWxmaWxsaW5nIGZ1bGwgb3IgcGFydGlhbCBjcml0ZXJpYSBmb3IgS2F3YXNha2kgZGlzZWFzZS4KMi4gRXhjbHVzaW9uIG9mIGFueSBvdGhlciBtaWNyb2JpYWwgY2F1c2UsIGluY2x1ZGluZyBiYWN0ZXJpYWwgc2Vwc2lzLCBzdGFwaHlsb2NvY2NhbCBvciBzdHJlcHRvY29jY2FsIHNob2NrIHN5bmRyb21lcywgaW5mZWN0aW9ucyBhc3NvY2lhdGVkIHdpdGggbXlvY2FyZGl0aXMgc3VjaCBhcyBlbnRlcm92aXJ1cyAod2FpdGluZyBmb3IgcmVzdWx0cyBvZiB0aGVzZSBpbnZlc3RpZ2F0aW9ucyBzaG91bGQgbm90IGRlbGF5IHNlZWtpbmcgZXhwZXJ0IGFkdmljZSkuCjMuIFNBUlMtQ29WLTIgUENSIHRlc3RpbmcgbWF5IGJlIHBvc2l0aXZlIG9yIG5lZ2F0aXZlIAoKV2UgYXJlIHVuYWJsZSB0byBldmFsdWF0ZSBjcml0ZXJpYSAyLgoKYGBge3IsIGZpZy5oZWlnaHQ9IDEwLCBmaWcud2lkdGg9IDh9ClBJTVNfVFNfZnVsZmlsbGVkIDwtIGFwcGx5KGRmX3NpbmdsZWNhc2VzLCAxLCBmdW5jdGlvbihyb3cpIHsKICAgICMgcGVyc2lzdGVudCBmZXZlciwgaW5mbGFtbWF0aW9uIChuZXV0cm9waGlsaWEsIGVsZXZhdGVkIENSUCBhbmQgbHltcGhvcGFlbmlhKSAKICAgIHBhdF9pZCA8LSByb3dbInBhdGllbnRJRF9pbnQiXQogICAgZmV2ZXIgPC0gcm93WyJzeW1wX2ZldmVyIl0gPT0gVFJVRQogICAgbmV1dHJvcGhpbGlhIDwtIGFzLm51bWVyaWMocm93WyJsYWJfbmV1dHJvcGhpbHMiXSkgPiBjb19uZXV0cm9waGlsaWEKICAgIGVsZXZhdGVkX0NSUCA8LSAoYXMubnVtZXJpYyhyb3dbImxhYl9DUlBfYWRtaXMiXSkgPiBjb19DUlAgfCBhcy5udW1lcmljKHJvd1sibGFiX0NSUF9OUyJdKSA+IGNvX0NSUCB8IGFzLm51bWVyaWMocm93WyJsYWJfQ1JQX3BlYWsiXSkgPiBjb19DUlAgKQogICAgbHltcGhvcGVuaWEgPC0gYXMubnVtZXJpYyhyb3dbImxhYl9seW1waG9jeXRlc19sb3dlc3QiXSkgPCBjb19seW1waG8KICAgIGluZmxhbW0gPC0gYW55KGZldmVyLCBuZXV0cm9waGlsaWEsIGVsZXZhdGVkX0NSUCwgbHltcGhvcGVuaWEpCiAgICAKICAgICMgbGFiIHZhbHVlcwogICAgI2ZpYnJpbm9nZW4gPC0gcm93WyJsYWJfZmlicmlubyJdID4gY29fZmlicmlubwogICAgI0RkaW1lcnMgPC0gcm93WyJsYWJfRGRpbV9wZWFrIl0gPiBjb19EZGltIHwgIHJvd1sibGFiX0RkaW1fTlMiXSA+IGNvX0RkaW0KICAgICNmZXJyaXRpbiA8LSAocm93WyJsYWJfZmVycml0aW5fTlMiXSA+IGNvX2ZlcnJpdGluIHwgcm93WyJsYWJfZmVycml0aW5fYWRtaXMiXSA+IGNvX2ZlcnJpdGluIHwgcm93WyJsYWJfZmVycml0aW5fcGVhayJdID4gY29fZmVycml0aW4pCiAgICAjYWxidW1pbiA8LSByb3dbImxhYl9hbGJ1bWluX2FkbWlzIl0gPCBjb19hbGJ1IHwgcm93WyJsYWJfYWxidW1pbl9sb3dlc3QiXSA8IGNvX2FsYnUgfCByb3dbImxhYl9hbGJ1bWluX05TIl0gPCBjb19hbGJ1CiAgICAjbGFiX3ZhbHMgPC0gYW55KGZpYnJpbm9nZW4sIERkaW1lcnMsIGZlcnJpdGluLCBhbGJ1bWluKQogICAgCiAgICAjIHNpbmdsZSBvciBtdWx0aS1vcmdhbiBkeXNmdW5jdGlvbiAoc2hvY2ssIGNhcmRpYWMsIHJlc3BpcmF0b3J5LCByZW5hbCwgZ2FzdHJvaW50ZXN0aW5hbCBvciBuZXVyb2xvZ2ljYWwgZGlzb3JkZXIpCiAgICBwbmV1bW9uaWEgPC0gcm93WyJzeW1wX3Jlc3BfcG5ldW1vbmlhIl0gPT0gVFJVRQogICAgcmVzcF9mYWlsdXJlIDwtIHJvd1sic3ltcF9yZXNwX2ZhaWx1cmUiXSA9PSBUUlVFCiAgICByZXNwIDwtIGFueShwbmV1bW9uaWEsIHJlc3BfZmFpbHVyZSkKICAgIAogICAgQUtJIDwtIHJvd1sic3ltcF9yZW5hbF9BS0kiXSA9PSBUUlVFCiAgICBSUlQgPC0gcm93WyJjcml0Y2FyZV9SUlQiXSA9PSBUUlVFCiAgICByZW5hbCA8LSBhbnkoQUtJLCBSUlQpCiAgICAKICAgIG15b2NhcmRpdGlzIDwtIHJvd1sic3ltcF9jYXJkaW92YXNjX215b2NhcmQiXSA9PSBUUlVFCiAgICBwZXJpY2FyZGl0aXMgPC0gcm93WyJzeW1wX2NhcmRpb3Zhc2NfcGVyaWNhcmQiXSA9PSBUUlVFCiAgICBMVkVGX3VuZGVyMzAgPC0gcm93WyJzeW1wX2NhcmRpb3Zhc2NfTFZfbGVzczMwIl0gPT0gVFJVRQogICAgTFZFRl8zMHRvNTUgPC0gcm93WyJzeW1wX2NhcmRpb3Zhc2NfTFZfMzB0bzU1Il0gPT0gVFJVRQogICAgQk5QIDwtIChhcy5udW1lcmljKHJvd1sibGFiX0JOUF9hZG1pcyJdKSA+IGNvX0JOUCB8IGFzLm51bWVyaWMocm93WyJsYWJfQk5QX21heCJdKSA+IGNvX0JOUCApIAogICAgTlRwcm9CTlAgPC0gYXMubnVtZXJpYyhyb3dbImxhYl9OVHByb0JOUCJdKSA+IGNvX05UcHJvQk5QCiAgICB0cm9wbyA8LSBhcy5udW1lcmljKHJvd1sibGFiX3Ryb3BvbmluX2FkbWlzIl0pID4gY29fdHJvcG8KICAgIHNob2NrIDwtIHJvd1sic3ltcF9jYXJkaW92YXNjX3Nob2NrIl0gPT0gVFJVRQogICAgCiAgICBjYXJkaW92YXNjIDwtIGFueShteW9jYXJkaXRpcywgTFZFRl91bmRlcjMwLCBMVkVGXzMwdG81NSwgTlRwcm9CTlAsIEJOUCwgdHJvcG8sIHNob2NrKQogICAgCiAgICByYXNoIDwtIHJvd1sia2F3YXNha2lfZXhhbnRoZW1hIl0gPT0gVFJVRQogICAgZGVybWF0byA8LSBhbnkocmFzaCkKICAgIAogICAgb3JnYW5fZHlzZnVuYyA8LSBzdW0ocmVzcCwgcmVuYWwsIGNhcmRpb3Zhc2MsIGRlcm1hdG8sIG5hLnJtID0gVFJVRSkgPj0gMQoKICAgIGNyaXRlcmlhX2Z1bGZpbGxlZCA8LSAoaW5mbGFtbSkgJiBvcmdhbl9keXNmdW5jICMmbGFiX3ZhbHMKICAgICNyZXR1cm4oYyhwYXRfaWQsICJjcml0ZXJpYTFfaW5mbGFtbSIgPSBpbmZsYW1tLCAiY3JpdGVyaWEyX2xhYnZhbHMiID0gbGFiX3ZhbHMsICJjcml0ZXJpYTNfb3JnYW5keXNmdW5jIiA9IG9yZ2FuX2R5c2Z1bmMsICJjcml0ZXJpYV9mdWxmaWxsZWQiID0gY3JpdGVyaWFfZnVsZmlsbGVkKSkKICAgIHJldHVybihjKHBhdF9pZCwgImNyaXRlcmlhMV9pbmZsYW1tIiA9IGluZmxhbW0sICJjcml0ZXJpYTJfb3JnYW5keXNmdW5jIiA9IG9yZ2FuX2R5c2Z1bmMsICJjcml0ZXJpYV9mdWxmaWxsZWQiID0gY3JpdGVyaWFfZnVsZmlsbGVkKSkKfSkKClBJTVNfVFNfZnVsZmlsbGVkIDwtIFBJTVNfVFNfZnVsZmlsbGVkICU+JSB0KCkgJT4lIGFzX3RpYmJsZSgpClBJTVNfVFNfZnVsZmlsbGVkIDwtIHR5cGVfY29udmVydChQSU1TX1RTX2Z1bGZpbGxlZCkKUElNU19UU19mdWxmaWxsZWRfaGVhdG1hcCA8LSBQSU1TX1RTX2Z1bGZpbGxlZApjb2xzIDwtIHNhcHBseShQSU1TX1RTX2Z1bGZpbGxlZF9oZWF0bWFwLCBpcy5sb2dpY2FsKQpQSU1TX1RTX2Z1bGZpbGxlZF9oZWF0bWFwWyxjb2xzXSA8LSBsYXBwbHkoUElNU19UU19mdWxmaWxsZWRfaGVhdG1hcFssY29sc10sIGFzLm51bWVyaWMpClBJTVNfVFNfZnVsZmlsbGVkX2hlYXRtYXBfbWVsdCA8LSBQSU1TX1RTX2Z1bGZpbGxlZF9oZWF0bWFwICU+JSBtZWx0KCkKUElNU19UU19mdWxmaWxsZWRfaGVhdG1hcF9tZWx0W2lzLm5hKFBJTVNfVFNfZnVsZmlsbGVkX2hlYXRtYXBfbWVsdCldIDwtIDIKCnNraW0oUElNU19UU19mdWxmaWxsZWQpCgojZ2dwbG90KFBJTVNfVFNfZnVsZmlsbGVkX2hlYXRtYXBfbWVsdCwgYWVzKHggPSB2YXJpYWJsZSwgeSA9IGFzLmNoYXJhY3RlcihwYXRpZW50SURfaW50KSwgZmlsbCA9IGFzLmZhY3Rvcih2YWx1ZSkpKSArIGdlb21fdGlsZSgpICsgdGhlbWVfY2xhc3NpYygpICsgdGhlbWUoYXhpcy5saW5lPWVsZW1lbnRfYmxhbmsoKSkgKyBsYWJzKHkgPSAiUGF0aWVudCBJRCIsIHggPSAiY3JpdGVyaWEiLCBmaWxsID0gImNyaXRlcmlhIG1ldCIsIHRpdGxlID0gIk92ZXJ2aWV3IG9mIHdoaWNoIHNpbmdsZSBjYXNlcyBmdWxmaWxsIFBJTVMtVFMgY2FzZSBkZWZpbml0aW9uIikgKyAgc2NhbGVfZmlsbF9tYW51YWwobGFiZWxzID0gYygiTm8iLCAiWWVzIiwgIk1pc3NpbmciKSwgdmFsdWVzID0gYygicGluazIiLCAicm95YWxibHVlMyIsICJkYXJrZ3JleSIpKSArIHRoZW1lKGF4aXMudGV4dC54PWVsZW1lbnRfdGV4dChhbmdsZT05MCwgaGp1c3Q9MSkpCmBgYAoKIyMjIENEQyBNSVMtQwpbU291cmNlIENEQ10oaHR0cHM6Ly93d3cuY2RjLmdvdi9taXMtYy9oY3AvKSBhbmQgW1VwVG9EYXRlXShodHRwczovL3d3dy51cHRvZGF0ZS5jb20vY29udGVudHMvaW1hZ2U/aW1hZ2VLZXk9UEVEUyUyRjEyODIwMSZ0b3BpY0tleT1QRURTJTJGMTI3NDg4KQpUaGUgY2FzZSBkZWZpbml0aW9uIGZvciBNSVMtQyBpczoKCjEuIEFnZSA8MjEgeWVhcnMKMi4gQ2xpbmljYWwgcHJlc2VudGF0aW9uIGNvbnNpc3RlbnQgd2l0aCBNSVMtQywgaW5jbHVkaW5nIGFsbCBvZiB0aGUgZm9sbG93aW5nOgogICAgLSBGZXZlcgogICAgICAgIC0gRG9jdW1lbnRlZCBmZXZlciA+MzguMMKwQyAoMTAwLjTCsEYpIGZvciDiiaUyNCBob3VycyBvcgogICAgICAgIC0gUmVwb3J0IG9mIHN1YmplY3RpdmUgZmV2ZXIgbGFzdGluZyDiiaUyNCBob3VycwogICAgLSBMYWJvcmF0b3J5IGV2aWRlbmNlIG9mIGluZmxhbW1hdGlvbgogICAgLSBTZXZlcmUgaWxsbmVzcyByZXF1aXJpbmcgaG9zcGl0YWxpemF0aW9uCiAgICAtIE11bHRpc3lzdGVtIGludm9sdmVtZW50CiAgICAgICAgLSAyIG9yIG1vcmUgb3JnYW4gc3lzdGVtcyBpbnZvbHZlZAogICAgICAgICAgICAtIENhcmRpb3Zhc2N1bGFyIChlZywgc2hvY2ssIGVsZXZhdGVkIHRyb3BvbmluLCBlbGV2YXRlZCBCTlAsIGFibm9ybWFsIGVjaG9jYXJkaW9ncmFtLCBhcnJoeXRobWlhKQogICAgICAgICAgICAtIFJlc3BpcmF0b3J5IChlZywgcG5ldW1vbmlhLCBBUkRTLCBwdWxtb25hcnkgZW1ib2xpc20pCiAgICAgICAgICAgIC0gUmVuYWwgKGVnLCBBS0ksIHJlbmFsIGZhaWx1cmUpCiAgICAgICAgICAgIC0gTmV1cm9sb2dpYyAoZWcsIHNlaXp1cmUsIHN0cm9rZSwgYXNlcHRpYyBtZW5pbmdpdGlzKQogICAgICAgICAgICAtIEhlbWF0b2xvZ2ljIChlZywgY29hZ3Vsb3BhdGh5KQogICAgICAgICAgICAtIEdhc3Ryb2ludGVzdGluYWwgKGVnLCBlbGV2YXRlZCBsaXZlciBlbnp5bWVzLCBkaWFycmhlYSwgaWxldXMsIGdhc3Ryb2ludGVzdGluYWwgYmxlZWRpbmcpCiAgICAgICAgICAgIC0gRGVybWF0b2xvZ2ljIChlZywgZXJ5dGhyb2Rlcm1hLCBtdWNvc2l0aXMsIG90aGVyIHJhc2gpCjMuIE5vIGFsdGVybmF0aXZlIHBsYXVzaWJsZSBkaWFnbm9zZXMKNC4gUmVjZW50IG9yIGN1cnJlbnQgU0FSUy1Db1YtMiBpbmZlY3Rpb24gb3IgZXhwb3N1cmUKICAgIC0gQW55IG9mIHRoZSBmb2xsb3dpbmc6CiAgICAtIFBvc2l0aXZlIFNBUlMtQ29WLTIgUlQtUENSCiAgICAtIFBvc2l0aXZlIHNlcm9sb2d5CiAgICAtIFBvc2l0aXZlIGFudGlnZW4gdGVzdAogICAgLSBDT1ZJRC0xOSBleHBvc3VyZSB3aXRoaW4gdGhlIDQgd2Vla3MgcHJpb3IgdG8gdGhlIG9uc2V0IG9mIHN5bXB0b21zCgoKCmBgYHtyLCBmaWcuaGVpZ2h0PSAxMCwgZmlnLndpZHRoPSA4fQoKQ0RDX2Z1bGZpbGxlZCA8LSBhcHBseShkZl9zaW5nbGVjYXNlcywgMSwgZnVuY3Rpb24ocm93KSB7CiAgICAjIGNyaXRlcmlhIDEKICAgIGNyaXRlcmlhMSA9IFRSVUUKICAgIAogICAgIyBjcml0ZXJpYSAyCiAgICBwYXRfaWQgPC0gcm93WyJwYXRpZW50SURfaW50Il0KICAgIAogICAgIyBmZXZlcj8KICAgIGZldmVyIDwtIHJvd1sic3ltcF9mZXZlciJdID09IFRSVUUgfCByb3dbImthd2FzYWtpX2ZldmVyIl0gPT0gVFJVRQoKICAgIGluZmxhbW0gPC0gYW55KGZldmVyKQogICAgCiAgICAjIGxhYiB2YWx1ZXMgZXZpZGVuY2UgZm9yIGluZmxhbW1hdGlvbgogICAgbmV1dHJvcGhpbGlhIDwtIGFzLm51bWVyaWMocm93WyJsYWJfbmV1dHJvcGhpbHMiXSkgPiBjb19uZXV0cm9waGlsaWEKICAgIGVsZXZhdGVkX0NSUCA8LSAoYXMubnVtZXJpYyhyb3dbImxhYl9DUlBfYWRtaXMiXSkgPiBjb19DUlAgfCBhcy5udW1lcmljKHJvd1sibGFiX0NSUF9OUyJdKSA+IGNvX0NSUCB8IGFzLm51bWVyaWMocm93WyJsYWJfQ1JQX3BlYWsiXSkgPiBjb19DUlAgKQogICAgbHltcGhvcGVuaWEgPC0gYXMubnVtZXJpYyhyb3dbImxhYl9seW1waG9jeXRlc19sb3dlc3QiXSkgPCBjb19seW1waG8KICAgIGZpYnJpbm9nZW4gPC0gYXMubnVtZXJpYyhyb3dbImxhYl9maWJyaW5vIl0pID4gY29fZmlicmlubwogICAgRGRpbWVycyA8LSBhcy5udW1lcmljKHJvd1sibGFiX0RkaW1fcGVhayJdKSA+IGNvX0RkaW0gfCAgYXMubnVtZXJpYyhyb3dbImxhYl9EZGltX05TIl0pID4gY29fRGRpbQogICAgZmVycml0aW4gPC0gKGFzLm51bWVyaWMocm93WyJsYWJfZmVycml0aW5fTlMiXSkgPiBjb19mZXJyaXRpbiB8IGFzLm51bWVyaWMocm93WyJsYWJfZmVycml0aW5fYWRtaXMiXSkgPiBjb19mZXJyaXRpbiB8IGFzLm51bWVyaWMocm93WyJsYWJfZmVycml0aW5fcGVhayJdKSA+IGNvX2ZlcnJpdGluKQogICAgYWxidW1pbiA8LSBhcy5udW1lcmljKHJvd1sibGFiX2FsYnVtaW5fYWRtaXMiXSkgPCBjb19hbGJ1IHwgYXMubnVtZXJpYyhyb3dbImxhYl9hbGJ1bWluX2xvd2VzdCJdKSA8IGNvX2FsYnUgfCBhcy5udW1lcmljKHJvd1sibGFiX2FsYnVtaW5fTlMiXSkgPCBjb19hbGJ1CiAgICBQQ1QgPC0gYXMubnVtZXJpYyhyb3dbImxhYl9QQ1RfYWRtaXMiXSkgPiBjb19QQ1QgfCBhcy5udW1lcmljKHJvd1sibGFiX1BDVF9wZWFrIl0pID4gY29fUENUIHwgYXMubnVtZXJpYyhyb3dbImxhYl9QQ1RfTlMiXSkgPiBjb19QQ1QgCiAgICBMREggPC0gYXMubnVtZXJpYyhyb3dbImxhYl9MREgiXSkgPiBjb19MREgKICAgIElMNiA8LSBhcy5udW1lcmljKHJvd1sibGFiX0lMNiJdKSA+IGNvX0lMNgogICAgRVNSIDwtIGFzLm51bWVyaWMocm93WyJsYWJfRVNSIl0pID4gY29fRVNSCgogICAgbGFiX3ZhbHMgPC0gYW55KG5ldXRyb3BoaWxpYSwgZWxldmF0ZWRfQ1JQLCBseW1waG9wZW5pYSwgZmlicmlub2dlbiwgRGRpbWVycywgZmVycml0aW4sIGFsYnVtaW4sIFBDVCwgTERILCBJTDYsIEVTUikKICAgIAogICAgIyBJbG5lc3MgcmVxdWlyaW5nIGhvc3BpdGFsaXNhdGlvbgogICAgIyMgdXNlZCBzdXJyb2dhdGUgcGFyYW1ldGVycyBmb3IgaG9zcAogICAgaG9zcF9JQ1UgPC0gcm93WyJhZG1pc19ob3NwX2RheXMiXSA+IDEgfCByb3dbImFkbWlzX0lDVV9kYXlzIl0gPiAxIHwgcm93WyJhZG1pc19QSUNVX2FkbWlzIl0gPT0gVFJVRQogICAgTklWIDwtIHJvd1siY3JpdGNhcmVfTklWIl0gPT0gVFJVRSB8IHJvd1siY3JpdGNhcmVfTklWX2RheXMiXSA+IDEKICAgIE1WIDwtIHJvd1siY3JpdGNhcmVfTVYiXSA9PSBUUlVFIHwgcm93WyJjcml0Y2FyZV9NVl9kYXlzIl0gPiAxCiAgICBpbm90cm9wIDwtIHJvd1siY3JpdGNhcmVfaW5vdHJvcCJdID09IFRSVUUgfCByb3dbImNyaXRjYXJlX2lub3Ryb3BfZGF5cyJdID4gMQogICAgRUNNTyA8LSByb3dbImNyaXRjYXJlX0VDTU8iXSA9PSBUUlVFIAogICAgSVZJZyA8LSByb3dbInJ4X0lWSWdfb25jZSJdID09IFRSVUUgIHwgIHJvd1sicnhfSVZJZ19tdWx0aXAiXSA9PSBUUlVFIAogICAgYmlvbG9naWNhbHMgPC0gcm93WyJyeF9hbmFraW5yYSJdID09IFRSVUUgfCByb3dbInJ4X3RvY2lsaXp1bWFiIl0gPT0gVFJVRSB8IHJvd1sicnhfaW5mbGl4aW1hYiJdID09IFRSVUUgfCByb3dbInJ4X2FudGliaW90aWNzIl0gPT0gVFJVRSB8IHJvd1sicnhfcGxhc21hIl0gPT0gVFJVRSB8IHJvd1sicnhfcmVtZGVzaXZpciJdID09IFRSVUUgCiAgICBoZXBhcmluIDwtIHJvd1sicnhfaGVwYXJpbiJdID09IFRSVUUKCgogICAgcmVxX2hvc3AgPC0gYW55KGhvc3BfSUNVLCBOSVYsIE1WLCBpbm90cm9wLCBFQ01PLCBJVklnLCBiaW9sb2dpY2FscywgaGVwYXJpbikKICAgIAogICAgIyMgbXVsdGlzeXN0ZW0gaW52b2x2ZW1lbnQgPj0gMgogICAgIyMgcmVzcGlyYXRvcnkKICAgIHBuZXVtb25pYSA8LSByb3dbInN5bXBfcmVzcF9wbmV1bW9uaWEiXSA9PSBUUlVFCiAgICByZXNwX2ZhaWx1cmUgPC0gcm93WyJzeW1wX3Jlc3BfZmFpbHVyZSJdID09IFRSVUUKICAgIHJlc3AgPC0gYW55KHBuZXVtb25pYSwgcmVzcF9mYWlsdXJlKQogICAgCiAgICBBS0kgPC0gcm93WyJzeW1wX3JlbmFsX0FLSSJdID09IFRSVUUKICAgIFJSVCA8LSByb3dbImNyaXRjYXJlX1JSVCJdID09IFRSVUUKICAgIHJlbmFsIDwtIGFueShBS0ksIFJSVCkKICAgIAogICAgbXlvY2FyZGl0aXMgPC0gcm93WyJzeW1wX2NhcmRpb3Zhc2NfbXlvY2FyZCJdID09IFRSVUUKICAgIHBlcmljYXJkaXRpcyA8LSByb3dbInN5bXBfY2FyZGlvdmFzY19wZXJpY2FyZCJdID09IFRSVUUKICAgIExWRUZfdW5kZXIzMCA8LSByb3dbInN5bXBfY2FyZGlvdmFzY19MVl9sZXNzMzAiXSA9PSBUUlVFCiAgICBMVkVGXzMwdG81NSA8LSByb3dbInN5bXBfY2FyZGlvdmFzY19MVl8zMHRvNTUiXSA9PSBUUlVFCiAgICBCTlAgPC0gKGFzLm51bWVyaWMocm93WyJsYWJfQk5QX2FkbWlzIl0pID4gY29fQk5QIHwgYXMubnVtZXJpYyhyb3dbImxhYl9CTlBfbWF4Il0pID4gY29fQk5QICkgCiAgICBOVHByb0JOUCA8LSBhcy5udW1lcmljKHJvd1sibGFiX05UcHJvQk5QIl0pID4gY29fTlRwcm9CTlAKICAgIHRyb3BvIDwtIGFzLm51bWVyaWMocm93WyJsYWJfdHJvcG9uaW5fYWRtaXMiXSkgPiBjb190cm9wbwogICAgc2hvY2sgPC0gcm93WyJzeW1wX2NhcmRpb3Zhc2Nfc2hvY2siXSA9PSBUUlVFCiAgICAKICAgIGNhcmRpb3Zhc2MgPC0gYW55KG15b2NhcmRpdGlzLCBMVkVGX3VuZGVyMzAsIExWRUZfMzB0bzU1LCBOVHByb0JOUCwgQk5QLCB0cm9wbywgc2hvY2spCiAgICAKICAgIHJhc2ggPC0gcm93WyJrYXdhc2FraV9leGFudGhlbWEiXSA9PSBUUlVFCiAgICBkZXJtYXRvIDwtIGFueShyYXNoKQogICAgCiAgICBvcmdhbl9keXNmdW5jIDwtIHN1bShyZXNwLCByZW5hbCwgY2FyZGlvdmFzYywgZGVybWF0bywgbmEucm0gPSBUUlVFKSA+PSAyCiAgICAKICAgIGNyaXRlcmlhMiA8LSBzdW0oaW5mbGFtbSwgbGFiX3ZhbHMsIHJlcV9ob3NwLCBvcmdhbl9keXNmdW5jLCBuYS5ybSA9IFRSVUUpID09IDQKICAgICMgY3JpdGVyaWEgMwogICAgIyMgbm90IGV2YWx1YWJsZQogICAgY3JpdGVyaWEzID0gVFJVRQogICAgIyBjcml0ZXJpYSA0CiAgICAjIENPVklEIHBvcz8KICAgIFBDUl9wb3MgPC0gcm93WyJjb3ZpZF9QQ1JfcG9zIl0gPT0gVFJVRQogICAgc3Rvb2xfcG9zIDwtIHJvd1siY292aWRfUENSX3N0b29sX3BvcyJdID09IFRSVUUKICAgIGNsb3NlY29udGFjdCA8LSByb3dbImNvdmlkX2Nsb3NlY29udGFjdCJdID09IFRSVUUKICAgIElnQSA8LSByb3dbImNvdmlkX0lnQV9wb3MiXSA9PSBUUlVFCiAgICBJZ00gPC0gcm93WyJjb3ZpZF9JZ01fcG9zIl0gPT0gVFJVRSAgICAKICAgIElnRyA8LSByb3dbImNvdmlkX0lnR19wb3MiXSA9PSBUUlVFICAgIAogICAgYW55X3Nlcm8gPC0gcm93WyJjb3ZpZF9zZXJvX3BvcyJdID09IFRSVUUKICAgIAogICAgY3JpdGVyaWE0IDwtIGFueShQQ1JfcG9zLCBzdG9vbF9wb3MsIGNsb3NlY29udGFjdCwgSWdBLCBJZ00sIElnRywgYW55X3Nlcm8pCiAgICAKICAgIGlmIChGQUxTRSAlaW4lIGMoY3JpdGVyaWExLCBjcml0ZXJpYTIsIGNyaXRlcmlhMywgY3JpdGVyaWE0KSl7CiAgICAgIGNyaXRlcmlhX2Z1bGZpbGxlZCA8LSBGQUxTRQogICAgfSBlbHNlIGlmIChOQSAlaW4lIGMoY3JpdGVyaWExLCBjcml0ZXJpYTIsIGNyaXRlcmlhMywgY3JpdGVyaWE0KSl7CiAgICAgIGNyaXRlcmlhX2Z1bGZpbGxlZCA8LSBOQQogICAgfSBlbHNlIGlmIChzdW0oY3JpdGVyaWExLCBjcml0ZXJpYTIsIGNyaXRlcmlhMywgY3JpdGVyaWE0LCBuYS5ybSA9IFRSVUUpID09IDQpewogICAgICBjcml0ZXJpYV9mdWxmaWxsZWQgPC0gVFJVRQogICAgfQogICAgCiAgICAjY3JpdGVyaWFfZnVsZmlsbGVkIDwtIHN1bShjcml0ZXJpYTEsIGNyaXRlcmlhMiwgY3JpdGVyaWEzLCBjcml0ZXJpYTQsIG5hLnJtID0gVFJVRSkgPT0gNAogICAgcmV0dXJuKGMocGF0X2lkLCAiY3JpdGVyaWExX2FnZSIgPSBjcml0ZXJpYTEsICJjcml0ZXJpYTJfY2xpbmljYWwiID0gY3JpdGVyaWEyLCAiY3JpdGVyaWEzX25vQWx0IiA9IGNyaXRlcmlhMywgImNyaXRlcmlhNF9yZWNlbnRFeHBvc3VyZSIgPSBjcml0ZXJpYTQsICJjcml0ZXJpYV9mdWxmaWxsZWQiID0gY3JpdGVyaWFfZnVsZmlsbGVkKSkKfSkKCkNEQ19mdWxmaWxsZWQgPC0gQ0RDX2Z1bGZpbGxlZCAlPiUgdCgpICU+JSBhc190aWJibGUoKQpDRENfZnVsZmlsbGVkIDwtIHR5cGVfY29udmVydChDRENfZnVsZmlsbGVkKQpDRENfZnVsZmlsbGVkX2hlYXRtYXAgPC0gQ0RDX2Z1bGZpbGxlZApjb2xzIDwtIHNhcHBseShDRENfZnVsZmlsbGVkX2hlYXRtYXAsIGlzLmxvZ2ljYWwpCkNEQ19mdWxmaWxsZWRfaGVhdG1hcFssY29sc10gPC0gbGFwcGx5KENEQ19mdWxmaWxsZWRfaGVhdG1hcFssY29sc10sIGFzLm51bWVyaWMpCkNEQ19mdWxmaWxsZWRfaGVhdG1hcF9tZWx0IDwtIENEQ19mdWxmaWxsZWRfaGVhdG1hcCAlPiUgbWVsdCgpCkNEQ19mdWxmaWxsZWRfaGVhdG1hcF9tZWx0W2lzLm5hKENEQ19mdWxmaWxsZWRfaGVhdG1hcF9tZWx0KV0gPC0gMgoKc2tpbShDRENfZnVsZmlsbGVkKQojZ2dwbG90KENEQ19mdWxmaWxsZWRfaGVhdG1hcF9tZWx0LCBhZXMoeCA9IHZhcmlhYmxlLCB5ID0gYXMuY2hhcmFjdGVyKHBhdGllbnRJRF9pbnQpLCBmaWxsID0gYXMuZmFjdG9yKHZhbHVlKSkpICsgZ2VvbV90aWxlKCkgKyB0aGVtZV9jbGFzc2ljKCkgKyB0aGVtZShheGlzLmxpbmU9ZWxlbWVudF9ibGFuaygpKSArIGxhYnMoeSA9ICJQYXRpZW50IElEIiwgeCA9ICJjcml0ZXJpYSIsIGZpbGwgPSAiY3JpdGVyaWEgbWV0IiwgdGl0bGUgPSAiT3ZlcnZpZXcgb2Ygd2hpY2ggc2luZ2xlIGNhc2VzIGZ1bGZpbGwgQ0RDIE1JUy1DIGNhc2UgZGVmaW5pdGlvbiIpICsgIHNjYWxlX2ZpbGxfbWFudWFsKGxhYmVscyA9IGMoIk5vIiwgIlllcyIsICJNaXNzaW5nIiksIHZhbHVlcyA9IGMoInBpbmsyIiwgInJveWFsYmx1ZTMiLCAiZGFya2dyZXkiKSkgKyB0aGVtZShheGlzLnRleHQueD1lbGVtZW50X3RleHQoYW5nbGU9OTAsIGhqdXN0PTEpKQpgYGAKCiMjIyBXSE8gY2FzZSBkZWZpbml0aW9uCltTb3VyY2UgVXBUb0RhdGVdKGh0dHBzOi8vd3d3LnVwdG9kYXRlLmNvbS9jb250ZW50cy9pbWFnZT9pbWFnZUtleT1QRURTJTJGMTI4MjAxJnRvcGljS2V5PVBFRFMlMkYxMjc0ODgpOgoKQWxsIDYgY3JpdGVyaWEgbXVzdCBiZSBtZXQ6CgoxLiBBZ2UgMCB0byAxOSB5ZWFycwoyLiBGZXZlciBmb3Ig4omlMyBkYXlzCjMuIENsaW5pY2FsIHNpZ25zIG9mIG11bHRpc3lzdGVtIGludm9sdmVtZW50IChhdCBsZWFzdCAyIG9mIHRoZSBmb2xsb3dpbmcpOgogICAgLSBSYXNoLCBiaWxhdGVyYWwgbm9ucHVydWxlbnQgY29uanVuY3Rpdml0aXMsIG9yIG11Y29jdXRhbmVvdXMgaW5mbGFtbWF0aW9uIHNpZ25zIChvcmFsLCBoYW5kcywgb3IgZmVldCkKICAgIC0gSHlwb3RlbnNpb24gb3Igc2hvY2sKICAgIC0gQ2FyZGlhYyBkeXNmdW5jdGlvbiwgcGVyaWNhcmRpdGlzLCB2YWx2dWxpdGlzLCBvciBjb3JvbmFyeSBhYm5vcm1hbGl0aWVzIChpbmNsdWRpbmcgZWNob2NhcmRpb2dyYXBoaWMgZmluZGluZ3Mgb3IgZWxldmF0ZWQgdHJvcG9uaW4vQk5QKQogICAgLSBFdmlkZW5jZSBvZiBjb2FndWxvcGF0aHkgKHByb2xvbmdlZCBQVCBvciBQVFQ7IGVsZXZhdGVkIEQtZGltZXIpCiAgICAtIEFjdXRlIGdhc3Ryb2ludGVzdGluYWwgc3ltcHRvbXMgKGRpYXJyaGVhLCB2b21pdGluZywgb3IgYWJkb21pbmFsIHBhaW4pCjQuIEVsZXZhdGVkIG1hcmtlcnMgb2YgaW5mbGFtbWF0aW9uIChlZywgRVNSLCBDUlAsIG9yIHByb2NhbGNpdG9uaW4pCjUuIE5vIG90aGVyIG9idmlvdXMgbWljcm9iaWFsIGNhdXNlIG9mIGluZmxhbW1hdGlvbiwgaW5jbHVkaW5nIGJhY3RlcmlhbCBzZXBzaXMgYW5kIHN0YXBoeWxvY29jY2FsL3N0cmVwdG9jb2NjYWwgdG94aWMgc2hvY2sgc3luZHJvbWVzCjYuIEV2aWRlbmNlIG9mIFNBUlMtQ29WLTIgaW5mZWN0aW9uCiAgICAtIEFueSBvZiB0aGUgZm9sbG93aW5nOgogICAgLSBQb3NpdGl2ZSBTQVJTLUNvVi0yIFJULVBDUgogICAgLSBQb3NpdGl2ZSBzZXJvbG9neQogICAgLSBQb3NpdGl2ZSBhbnRpZ2VuIHRlc3QKICAgIC0gQ29udGFjdCB3aXRoIGFuIGluZGl2aWR1YWwgd2l0aCBDT1ZJRC0xOQoKYGBge3IsIGZpZy5oZWlnaHQ9IDEwLCBmaWcud2lkdGg9IDh9CiNyb3cgPC0gZGZfc2luZ2xlY2FzZXNbODcsIF0KV0hPX2Z1bGZpbGxlZCA8LSBhcHBseShkZl9zaW5nbGVjYXNlcywgMSwgZnVuY3Rpb24ocm93KSB7CiAgICBwYXRfaWQgPC0gcm93WyJwYXRpZW50SURfaW50Il0KICAgIAogICAgIyBjcml0ZXJpYSAxCiAgICBjcml0ZXJpYTEgPSBUUlVFCiAgICAKICAgICMgY3JpdGVyaWEgMjogZmV2ZXI/CiAgICBmZXZlciA8LSByb3dbInN5bXBfZmV2ZXIiXSA9PSBUUlVFIHwgcm93WyJrYXdhc2FraV9mZXZlciJdID09IFRSVUUKCiAgICBjcml0ZXJpYTIgPC0gYW55KGZldmVyKQogICAgCiAgICAjIGNyaXRlcmlhIDM6IGNsaW5pY2FsIHNpZ25zIG9mIG11bHRpc3lzdGVtIGludm9sdmVtZW50IChhdCBsZWFzdCAyKQogICAgIyMgUmFzaCwgYmlsYXRlcmFsIG5vbnB1cnVsZW50IGNvbmp1bmN0aXZpdGlzLCBvciBtdWNvY3V0YW5lb3VzIGluZmxhbW1hdGlvbiBzaWducyAob3JhbCwgaGFuZHMsIG9yIGZlZXQpCiAgICByYXNoIDwtIHJvd1sia2F3YXNha2lfZXhhbnRoZW1hIl0gPT0gVFJVRQogICAgY29uanVuY3Rpdml0aXMgPC0gcm93WyJrYXdhc2FraV9jb25qdW5jdGl2aXRpcyJdID09IFRSVUUKICAgIG11Y29jdXRhbmVhb3VzIDwtIHJvd1sia2F3YXNha2lfbW91dGgiXSA9PSBUUlVFIHwgcm93WyJrYXdhc2FraV9leHRyZW1pdHkiXSA9PSBUUlVFCiAgICAKICAgIGNyaXRlcmlhM19hIDwtIGFueShyYXNoLCBjb25qdW5jdGl2aXRpcywgbXVjb2N1dGFuZWFvdXMpCiAgICAKICAgICMjIGh5cG90ZW5zaW9uIG9yIHNob2NrCiAgICBzaG9jayA8LSByb3dbInN5bXBfY2FyZGlvdmFzY19zaG9jayJdID09IFRSVUUKICAgIGNyaXRlcmlhM19iIDwtIGFueShzaG9jaykKICAgIAogICAgIyMgY2FyZGlhYyBkeXNmdW5jdGlvbgogICAgbXlvY2FyZGl0aXMgPC0gcm93WyJzeW1wX2NhcmRpb3Zhc2NfbXlvY2FyZCJdID09IFRSVUUKICAgIHBlcmljYXJkaXRpcyA8LSByb3dbInN5bXBfY2FyZGlvdmFzY19wZXJpY2FyZCJdID09IFRSVUUKICAgIExWRUZfdW5kZXIzMCA8LSByb3dbInN5bXBfY2FyZGlvdmFzY19MVl9sZXNzMzAiXSA9PSBUUlVFCiAgICBMVkVGXzMwdG81NSA8LSByb3dbInN5bXBfY2FyZGlvdmFzY19MVl8zMHRvNTUiXSA9PSBUUlVFCiAgICBCTlAgPC0gKGFzLm51bWVyaWMocm93WyJsYWJfQk5QX2FkbWlzIl0pID4gY29fQk5QIHwgYXMubnVtZXJpYyhyb3dbImxhYl9CTlBfbWF4Il0pID4gY29fQk5QICkgCiAgICBOVHByb0JOUCA8LSBhcy5udW1lcmljKHJvd1sibGFiX05UcHJvQk5QIl0pID4gY29fTlRwcm9CTlAKICAgIHRyb3BvIDwtIGFzLm51bWVyaWMocm93WyJsYWJfdHJvcG9uaW5fYWRtaXMiXSkgPiBjb190cm9wbwogICAgY29yb25hcnkgPC0gcm93WyJzeW1wX2NhcmRpb3Zhc2NfY29yZGlsYXQiXSA9PSBUUlVFIHwgcm93WyJzeW1wX2NhcmRpb3Zhc2NfYW5ldXJ5c20iXSA9PSBUUlVFCiAgICAKICAgIGNyaXRlcmlhM19jIDwtIGFueShteW9jYXJkaXRpcywgTFZFRl91bmRlcjMwLCBMVkVGXzMwdG81NSwgTlRwcm9CTlAsIEJOUCwgdHJvcG8sIGNvcm9uYXJ5KQogICAgCiAgICAjIyBjb2FndWxvcGF0aHkKICAgIGZpYnJpbm9nZW4gPC0gYXMubnVtZXJpYyhyb3dbImxhYl9maWJyaW5vIl0pID4gY29fZmlicmlubwogICAgRGRpbWVycyA8LSBhcy5udW1lcmljKHJvd1sibGFiX0RkaW1fcGVhayJdKSA+IGNvX0RkaW0gfCAgYXMubnVtZXJpYyhyb3dbImxhYl9EZGltX05TIl0pID4gY29fRGRpbQogICAgCiAgICBjcml0ZXJpYTNfZCA8LSBhbnkoZmlicmlub2dlbiwgRGRpbWVycykKICAgIAogICAgIyMgYWN1dGUgR0kgc3ltcHRvbXMKICAgIEdJc3ltcCA8LSByb3dbInN5bXBfR0lfTlMiXSA9PSBUUlVFIHwgcm93WyJzeW1wX0dJX2FiZG9wYWluIl0gPT0gVFJVRSB8IHJvd1sic3ltcF9HSV92b21pdGluZyJdID09IFRSVUUgfCByb3dbInN5bXBfR0lfZGlhcnJoIl0gPT0gVFJVRSB8IHJvd1sic3ltcF9HSV9jb2xpdGlzIl0gPT0gVFJVRSAKICAgIAogICAgY3JpdGVyaWEzX2UgPC0gYW55KEdJc3ltcCkKICAgIAogICAgY3JpdGVyaWEzIDwtIHN1bShjcml0ZXJpYTNfYSwgY3JpdGVyaWEzX2IsIGNyaXRlcmlhM19jLCBjcml0ZXJpYTNfZCwgY3JpdGVyaWEzX2UsIG5hLnJtID0gVFJVRSkgPj0gMgogICAgICAKICAgICMgY3JpdGVyaWEgNDogRWxldmF0ZWQgbWFya2VycyBvZiBpbmZsYW1tYXRpb24gKGVnLCBFU1IsIENSUCwgb3IgcHJvY2FsY2l0b25pbikKICAgIG5ldXRyb3BoaWxpYSA8LSBhcy5udW1lcmljKHJvd1sibGFiX25ldXRyb3BoaWxzIl0pID4gY29fbmV1dHJvcGhpbGlhCiAgICBlbGV2YXRlZF9DUlAgPC0gKGFzLm51bWVyaWMocm93WyJsYWJfQ1JQX2FkbWlzIl0pID49IGNvX0NSUCkgfCAoYXMubnVtZXJpYyhyb3dbImxhYl9DUlBfTlMiXSkgPj0gY29fQ1JQKSB8IChhcy5udW1lcmljKHJvd1sibGFiX0NSUF9wZWFrIl0pID49IGNvX0NSUCApCiAgIyAgcHJpbnQocGFzdGUwKHBhdF9pZCwgZWxldmF0ZWRfQ1JQLCByb3dbImxhYl9DUlBfcGVhayJdKSkKICAgIGx5bXBob3BlbmlhIDwtIGFzLm51bWVyaWMocm93WyJsYWJfbHltcGhvY3l0ZXNfbG93ZXN0Il0pIDwgY29fbHltcGhvCgogICAgZmVycml0aW4gPC0gKGFzLm51bWVyaWMocm93WyJsYWJfZmVycml0aW5fTlMiXSkgPiBjb19mZXJyaXRpbiB8IGFzLm51bWVyaWMocm93WyJsYWJfZmVycml0aW5fYWRtaXMiXSkgPiBjb19mZXJyaXRpbiB8IGFzLm51bWVyaWMocm93WyJsYWJfZmVycml0aW5fcGVhayJdKSA+IGNvX2ZlcnJpdGluKQogICAgYWxidW1pbiA8LSBhcy5udW1lcmljKHJvd1sibGFiX2FsYnVtaW5fYWRtaXMiXSkgPCBjb19hbGJ1IHwgYXMubnVtZXJpYyhyb3dbImxhYl9hbGJ1bWluX2xvd2VzdCJdKSA8IGNvX2FsYnUgfCBhcy5udW1lcmljKHJvd1sibGFiX2FsYnVtaW5fTlMiXSkgPCBjb19hbGJ1CiAgICBQQ1QgPC0gYXMubnVtZXJpYyhyb3dbImxhYl9QQ1RfYWRtaXMiXSkgPiBjb19QQ1QgfCBhcy5udW1lcmljKHJvd1sibGFiX1BDVF9wZWFrIl0pID4gY29fUENUIHwgYXMubnVtZXJpYyhyb3dbImxhYl9QQ1RfTlMiXSkgPiBjb19QQ1QgCiAgICBMREggPC0gYXMubnVtZXJpYyhyb3dbImxhYl9MREgiXSkgPiBjb19MREgKICAgIElMNiA8LSBhcy5udW1lcmljKHJvd1sibGFiX0lMNiJdKSA+IGNvX0lMNgogICAgRVNSIDwtIGFzLm51bWVyaWMocm93WyJsYWJfRVNSIl0pID4gY29fRVNSCgogICAgY3JpdGVyaWE0IDwtIGFueShuZXV0cm9waGlsaWEsIGVsZXZhdGVkX0NSUCwgbHltcGhvcGVuaWEsIGZlcnJpdGluLCBhbGJ1bWluLCBQQ1QsIExESCwgSUw2LCBFU1IpCgogICAgIyBjcml0ZXJpYSA1OiBObyBvdGhlciBvYnZpb3VzIG1pY3JvYmlhbCBjYXVzZSBvZiBpbmZsYW1tYXRpb24KICAgIGNyaXRlcmlhNSA8LSBUUlVFCiAgICAKICAgICMgY3JpdGVyaWEgNjogQ09WSUQgcG9zPwogICAgUENSX3BvcyA8LSByb3dbImNvdmlkX1BDUl9wb3MiXSA9PSBUUlVFCiAgICBzdG9vbF9wb3MgPC0gcm93WyJjb3ZpZF9QQ1Jfc3Rvb2xfcG9zIl0gPT0gVFJVRQogICAgY2xvc2Vjb250YWN0IDwtIHJvd1siY292aWRfY2xvc2Vjb250YWN0Il0gPT0gVFJVRQogICAgSWdBIDwtIHJvd1siY292aWRfSWdBX3BvcyJdID09IFRSVUUKICAgIElnTSA8LSByb3dbImNvdmlkX0lnTV9wb3MiXSA9PSBUUlVFICAgIAogICAgSWdHIDwtIHJvd1siY292aWRfSWdHX3BvcyJdID09IFRSVUUgICAgCiAgICBhbnlfc2VybyA8LSByb3dbImNvdmlkX3Nlcm9fcG9zIl0gPT0gVFJVRQogICAgCiAgICBjcml0ZXJpYTYgPC0gYW55KFBDUl9wb3MsIHN0b29sX3BvcywgY2xvc2Vjb250YWN0LCBJZ0EsIElnTSwgSWdHLCBhbnlfc2VybykKICAgIAogICAgaWYgKE5BICVpbiUgYyhjcml0ZXJpYTEsIGNyaXRlcmlhMiwgY3JpdGVyaWEzLCBjcml0ZXJpYTQsIGNyaXRlcmlhNSwgY3JpdGVyaWE2KSl7CiAgICAgIGNyaXRlcmlhX2Z1bGZpbGxlZCA8LSBOQQogICAgfSBlbHNlIGlmIChGQUxTRSAlaW4lIGMoY3JpdGVyaWExLCBjcml0ZXJpYTIsIGNyaXRlcmlhMywgY3JpdGVyaWE0LCBjcml0ZXJpYTUsIGNyaXRlcmlhNikpewogICAgICBjcml0ZXJpYV9mdWxmaWxsZWQgPC0gRkFMU0UKICAgIH0gZWxzZSBpZiAoc3VtKGNyaXRlcmlhMSwgY3JpdGVyaWEyLCBjcml0ZXJpYTMsIGNyaXRlcmlhNCwgY3JpdGVyaWE1LCBjcml0ZXJpYTYsIG5hLnJtID0gVFJVRSkgPT0gNil7CiAgICAgIGNyaXRlcmlhX2Z1bGZpbGxlZCA8LSBUUlVFCiAgICB9IGVsc2UgewogICAgICBjcml0ZXJpYV9mdWxmaWxsZWQgPC0gRkFMU0UKICAgIH0KCiAgICByZXR1cm4oYyhwYXRfaWQsICJjcml0ZXJpYTFfYWdlIiA9IGNyaXRlcmlhMSwgImNyaXRlcmlhMl9mZXZlciIgPSBjcml0ZXJpYTIsICJjcml0ZXJpYTNfY2xpbmljYWwiID0gY3JpdGVyaWEzLCAiY3JpdGVyaWE0X2luZmxhbW0iID0gY3JpdGVyaWE0LCAiY3JpdGVyaWE1X25vQWx0IiA9IGNyaXRlcmlhNSwgImNyaXRlcmlhNl9yZWNlbnRFeHBvc3VyZSIgPSBjcml0ZXJpYTYsICJjcml0ZXJpYV9mdWxmaWxsZWQiID0gY3JpdGVyaWFfZnVsZmlsbGVkKSkKfSkKCgpXSE9fZnVsZmlsbGVkIDwtIFdIT19mdWxmaWxsZWQgJT4lIHQoKSAlPiUgYXNfdGliYmxlKCkKV0hPX2Z1bGZpbGxlZCA8LSB0eXBlX2NvbnZlcnQoV0hPX2Z1bGZpbGxlZCkKV0hPX2Z1bGZpbGxlZF9oZWF0bWFwIDwtIFdIT19mdWxmaWxsZWQKY29scyA8LSBzYXBwbHkoV0hPX2Z1bGZpbGxlZF9oZWF0bWFwLCBpcy5sb2dpY2FsKQpXSE9fZnVsZmlsbGVkX2hlYXRtYXBbLGNvbHNdIDwtIGxhcHBseShXSE9fZnVsZmlsbGVkX2hlYXRtYXBbLGNvbHNdLCBhcy5udW1lcmljKQpXSE9fZnVsZmlsbGVkX2hlYXRtYXBfbWVsdCA8LSBXSE9fZnVsZmlsbGVkX2hlYXRtYXAgJT4lIG1lbHQoKQpXSE9fZnVsZmlsbGVkX2hlYXRtYXBfbWVsdFtpcy5uYShXSE9fZnVsZmlsbGVkX2hlYXRtYXBfbWVsdCldIDwtIDIKCnNraW0oV0hPX2Z1bGZpbGxlZCkKCiNnZ3Bsb3QoV0hPX2Z1bGZpbGxlZF9oZWF0bWFwX21lbHQsIGFlcyh4ID0gdmFyaWFibGUsIHkgPSBhcy5jaGFyYWN0ZXIocGF0aWVudElEX2ludCksIGZpbGwgPSBhcy5mYWN0b3IodmFsdWUpKSkgKyBnZW9tX3RpbGUoKSArIHRoZW1lX2NsYXNzaWMoKSArIHRoZW1lKGF4aXMubGluZT1lbGVtZW50X2JsYW5rKCkpICsgbGFicyh5ID0gIlBhdGllbnQgSUQiLCB4ID0gImNyaXRlcmlhIiwgZmlsbCA9ICJjcml0ZXJpYSBtZXQiLCB0aXRsZSA9ICJPdmVydmlldyBvZiB3aGljaCBzaW5nbGUgY2FzZXMgZnVsZmlsbCBXSE8gTUlTLUMgY2FzZSBkZWZpbml0aW9uIikgKyAgc2NhbGVfZmlsbF9tYW51YWwobGFiZWxzID0gYygiTm8iLCAiWWVzIiwgIk1pc3NpbmciKSwgdmFsdWVzID0gYygicGluazIiLCAicm95YWxibHVlMyIsICJkYXJrZ3JleSIpKSArIHRoZW1lKGF4aXMudGV4dC54PWVsZW1lbnRfdGV4dChhbmdsZT05MCwgaGp1c3Q9MSkpCmBgYAoKIyMgUGVyLWNhc2Ugb3ZlcnZpZXcKYGBge3IsIGZpZy5oZWlnaHQgPSAxMCwgZmlnLndpZHRoPTd9ClBJTVNfVFNfZnVsZmlsbGVkX2hlYXRtYXBfbWVsdCRjcml0ZXJpYSA8LSAiUElNUy1UUyIKV0hPX2Z1bGZpbGxlZF9oZWF0bWFwX21lbHQkY3JpdGVyaWEgPC0gIldITyIKQ0RDX2Z1bGZpbGxlZF9oZWF0bWFwX21lbHQkY3JpdGVyaWEgPC0gIkNEQyIKCmZ1bGxfaGVhdG1hcCA8LSByYmluZChQSU1TX1RTX2Z1bGZpbGxlZF9oZWF0bWFwX21lbHQsIFdIT19mdWxmaWxsZWRfaGVhdG1hcF9tZWx0LCBDRENfZnVsZmlsbGVkX2hlYXRtYXBfbWVsdCkKCmdncGxvdChmdWxsX2hlYXRtYXAsIGFlcyh4ID0gdmFyaWFibGUsIHkgPSBhcy5jaGFyYWN0ZXIocGF0aWVudElEX2ludCksIGZpbGwgPSBhcy5mYWN0b3IodmFsdWUpKSkgKyBnZW9tX3RpbGUoKSArIHRoZW1lX2NsYXNzaWMoKSArIHRoZW1lKGF4aXMubGluZT1lbGVtZW50X2JsYW5rKCkpICsgbGFicyh5ID0gIlBhdGllbnQgSUQiLCB4ID0gImNyaXRlcmlhIiwgZmlsbCA9ICJjcml0ZXJpYSBtZXQiLCB0aXRsZSA9ICJPdmVydmlldyBvZiB3aGljaCBzaW5nbGUgY2FzZXMgZnVsZmlsbCBjYXNlIGRlZmluaXRpb25zIikgKyAgc2NhbGVfZmlsbF9tYW51YWwobGFiZWxzID0gYygiTm8iLCAiWWVzIiwgIk1pc3NpbmciKSwgdmFsdWVzID0gd2VzX3BhbGV0dGUoIlppc3NvdTEiKSkgKyB0aGVtZShheGlzLnRleHQueD1lbGVtZW50X3RleHQoYW5nbGU9OTAsIGhqdXN0PTEpKSArIGZhY2V0X3dyYXAofiBjcml0ZXJpYSwgc2NhbGVzID0gImZyZWVfeCIpCgoKYGBgCgoKIyMgU3VtbWFyeQpgYGB7cn0KY3JpdGVyaWFfc3VtbWFyeSA8LSBkYXRhLmZyYW1lKFBJTVNfVFNfZnVsZmlsbGVkICU+JSBzZWxlY3QoY3JpdGVyaWFfZnVsZmlsbGVkKSwgQ0RDX2Z1bGZpbGxlZCAlPiUgc2VsZWN0KGNyaXRlcmlhX2Z1bGZpbGxlZCksIFdIT19mdWxmaWxsZWQgJT4lIHNlbGVjdChjcml0ZXJpYV9mdWxmaWxsZWQpKQpjb2xuYW1lcyhjcml0ZXJpYV9zdW1tYXJ5KSA8LSBjKCJQSU1TLVRTIiwgIkNEQyIsICJXSE8iKQoKY29scyA8LSBzYXBwbHkoY3JpdGVyaWFfc3VtbWFyeSwgaXMubG9naWNhbCkKY3JpdGVyaWFfc3VtbWFyeVssY29sc10gPC0gbGFwcGx5KGNyaXRlcmlhX3N1bW1hcnlbLGNvbHNdLCBhcy5udW1lcmljKQoKY3JpdGVyaWFfc3VtbWFyeSA8LSBjcml0ZXJpYV9zdW1tYXJ5ICU+JSBtZWx0KCkgJT4lIAogICAgICAgICAgICAgICAgICAgICAgICAgIGdyb3VwX2J5KHZhcmlhYmxlKSAlPiUgCiAgICAgICAgICAgICAgICAgICAgICAgICAgc3VtbWFyaXNlKGZ1bGZpbGxlZCA9IHN1bSh2YWx1ZSA9PSAxLCBuYS5ybSA9IFRSVUUpLCBub3RfZnVsZmlsbGVkID0gc3VtKHZhbHVlID09IDAsIG5hLnJtID0gVFJVRSksIG5vdF9ldmFsdWFibGUgPSBzdW0oaXMubmEodmFsdWUpKSkKY3JpdGVyaWFfc3VtbWFyeSRzdW0gPC0gcm93U3Vtcyhjcml0ZXJpYV9zdW1tYXJ5WywtMV0pCgpjcml0ZXJpYV9zdW1tYXJ5X21lbHQgPC0gY3JpdGVyaWFfc3VtbWFyeSAlPiUgbWVsdCgpCmNvbG5hbWVzKGNyaXRlcmlhX3N1bW1hcnlfbWVsdCkgPC0gYygiY2VudGVyIiwgImZ1bGZpbGxlZCIsICJjb3VudCIpCgpmaWxsX2JhciA8LSBnZ3Bsb3QoY3JpdGVyaWFfc3VtbWFyeV9tZWx0ICU+JSBmaWx0ZXIoZnVsZmlsbGVkICE9ICdzdW0nKSwgYWVzKHggPSBjZW50ZXIsIHkgPSBjb3VudCwgZmlsbCA9IGZ1bGZpbGxlZCkpICsgCiAgICAgIGdlb21fYmFyKHN0YXQgPSAiaWRlbnRpdHkiLCBwb3NpdGlvbiA9ICJmaWxsIikgKyB0aGVtZV9idygpICsgCiAgICAgIGxhYnMoeSA9ICJyYXRpbyIsIHRpdGxlID0gIlNpbmdsZSBjYXNlcyBtZWV0aW5nIHdoaWNoIGNyaXRlcmlhIiwgc3VidGl0bGUgPSBwYXN0ZTAoInBlcmNlbnQgb2YgdG90YWwgKG4gPSAiLCBtYXgoY3JpdGVyaWFfc3VtbWFyeV9tZWx0JGNvdW50KSAsIikiKSkgKwogICAgICAgIHNjYWxlX2ZpbGxfbWFudWFsKHZhbHVlcyA9IHdlc19wYWxldHRlKCJSb3lhbDEiKVtjKDEsMiw0KV0pCgpkb2RnZV9iYXIgPC0gZ2dwbG90KGNyaXRlcmlhX3N1bW1hcnlfbWVsdCAlPiUgZmlsdGVyKGZ1bGZpbGxlZCAhPSAnc3VtJyksIGFlcyh4ID0gY2VudGVyLCB5ID0gY291bnQsIGZpbGwgPSBmdWxmaWxsZWQpKSArIAogICAgICBnZW9tX2JhcihzdGF0ID0gImlkZW50aXR5IiwgcG9zaXRpb24gPSAiZG9kZ2UiKSArIHRoZW1lX2J3KCkgKyAKICAgICAgbGFicyh5ID0gIm4iLCB0aXRsZSA9ICJTaW5nbGUgY2FzZXMgbWVldGluZyB3aGljaCBjcml0ZXJpYSIsIHN1YnRpdGxlID0gImFic29sdXRlIHZhbHVlcyIpICsKICAgICAgICBzY2FsZV9maWxsX21hbnVhbCh2YWx1ZXMgPSB3ZXNfcGFsZXR0ZSgiUm95YWwxIilbYygxLDIsNCldKQoKZ2dhcnJhbmdlKGRvZGdlX2JhciwgZmlsbF9iYXIsIGxlZ2VuZCA9ICJib3R0b20iLCBjb21tb24ubGVnZW5kID0gVFJVRSkKYGBgCgojIEFzc29jaWF0aW9uIG9mIGNhc2UgZGVmaW5pdGlvbiB3aXRoIG91dGNvbWUKYGBge3J9CldIT19vdXRjb21lIDwtIFdIT19mdWxmaWxsZWRfaGVhdG1hcCAlPiUgc2VsZWN0KGNvbnRhaW5zKCJwYXRpZW50SURfaW50IikgfCBjb250YWlucygiY3JpdGVyaWFfZnVsZmlsbGVkIikpCmNvbG5hbWVzKFdIT19vdXRjb21lKSA8LSBjKCJwYXRpZW50SURfaW50IiwgImNhc2VkZWZfV0hPX2Z1bGZpbGxlZCIpCgpDRENfb3V0Y29tZSA8LSBDRENfZnVsZmlsbGVkX2hlYXRtYXAgJT4lIHNlbGVjdChjb250YWlucygicGF0aWVudElEX2ludCIpIHwgY29udGFpbnMoImNyaXRlcmlhX2Z1bGZpbGxlZCIpKQpjb2xuYW1lcyhDRENfb3V0Y29tZSkgPC0gYygicGF0aWVudElEX2ludCIsICJjYXNlZGVmX0NEQ19mdWxmaWxsZWQiKQoKUElNU19UU19vdXRjb21lIDwtIFBJTVNfVFNfZnVsZmlsbGVkX2hlYXRtYXAgJT4lIHNlbGVjdChjb250YWlucygicGF0aWVudElEX2ludCIpIHwgY29udGFpbnMoImNyaXRlcmlhX2Z1bGZpbGxlZCIpKQpjb2xuYW1lcyhQSU1TX1RTX291dGNvbWUpIDwtIGMoInBhdGllbnRJRF9pbnQiLCAiY2FzZWRlZl9QSU1TX1RTX2Z1bGZpbGxlZCIpCgphc3NvY19vdXRjb21lIDwtIG1lcmdlKFdIT19vdXRjb21lLCBDRENfb3V0Y29tZSwgYnkgPSAicGF0aWVudElEX2ludCIpCmFzc29jX291dGNvbWUgPC0gbWVyZ2UoYXNzb2Nfb3V0Y29tZSwgUElNU19UU19vdXRjb21lKQojYXNzb2Nfb3V0Y29tZSA8LSBhc3NvY19vdXRjb21lW2NvbXBsZXRlLmNhc2VzKGFzc29jX291dGNvbWVbICwtMV0pLF0KCm91dGNvbWVfcGFyYW1zIDwtIGRmX3NpbmdsZWNhc2VzICU+JSBzZWxlY3QocGF0aWVudElEX2ludCB8IHN5bXBfY2FyZGlvdmFzY19jb3JkaWxhdCB8IHN5bXBfY2FyZGlvdmFzY19hbmV1cnlzbSB8IHN5bXBfY2FyZGlvdmFzY19zaG9jayB8IG91dGNvbWVfZGVhdGggfCBjcml0Y2FyZV9NViB8IGNyaXRjYXJlX0VDTU8pCgphc3NvY19vdXRjb21lX2Z1bGwgPC0gbWVyZ2Uob3V0Y29tZV9wYXJhbXMsIGFzc29jX291dGNvbWUsIGJ5ID0gInBhdGllbnRJRF9pbnQiLCBhbGwgPSBUUlVFKQoKY29scyA8LSBzYXBwbHkoYXNzb2Nfb3V0Y29tZV9mdWxsLCBpcy5sb2dpY2FsKQphc3NvY19vdXRjb21lX2Z1bGxbLGNvbHNdIDwtIGxhcHBseShhc3NvY19vdXRjb21lX2Z1bGxbLGNvbHNdLCBhcy5udW1lcmljKQoKbWFrZVVwc2V0Uihhc3NvY19vdXRjb21lX2Z1bGwgJT4lIHNlbGVjdCgtY29udGFpbnMoInBhdGllbnRJRCIpKSkKYGBgCgojIyBVbmZhdm91cmFibGUgY291cnNlCkEgbmV3IHZhcmlhYmxlICd1bmZhdm91cmFibGUgY291cnNlJyBtYWRlLCB3aGljaCBjb250YWlucyB0aGUgZm9sbG93aW5nOgoKLSBzeW1wX2NhcmRpb3Zhc2NfY29yZGlsYXQgCi0gc3ltcF9jYXJkaW92YXNjX2FuZXVyeXNtCi0gc3ltcF9jYXJkaW92YXNjX3Nob2NrIAotIG91dGNvbWVfZGVhdGgKLSBjcml0Y2FyZV9NViAKLSBjcml0Y2FyZV9FQ01PCi0gY3JpdGNhcmVfUlJUCi0gY3JpdGNhcmVfaW5vdHJvcAotIGFkbWlzX1BJQ1VfYWRtaXMKCk1pbGQgcHJlc2VudGF0aW9uIG1lYW5zIGFsbCBvZiB0aGUgYWJvdmUgYXJlIGVpdGhlciAwIG9yIE5BLiAKCmBgYHtyfQphc3NvY19vdXRjb21lIDwtIG1lcmdlKFdIT19vdXRjb21lLCBDRENfb3V0Y29tZSwgYnkgPSAicGF0aWVudElEX2ludCIpCmFzc29jX291dGNvbWUgPC0gbWVyZ2UoYXNzb2Nfb3V0Y29tZSwgUElNU19UU19vdXRjb21lKQojYXNzb2Nfb3V0Y29tZSA8LSAjYXNzb2Nfb3V0Y29tZVtjb21wbGV0ZS5jYXNlcyhhc3NvY19vdXRjb21lWyAsLTFdKSxdCgpvdXRjb21lX3BhcmFtcyA8LSBkZl9zaW5nbGVjYXNlcyAlPiUgc2VsZWN0KHBhdGllbnRJRF9pbnQgfCBjb250YWlucygiY3JpdGNhcmUiKSAgfCBjb250YWlucygiYWRtaXNfUElDVV9hZG1pcyIpIHwgY29udGFpbnMoIm91dGNvbWVfZGVhdGgiKSAgfGNvbnRhaW5zICgic3ltcF9jYXJkaW92YXNjX2NvcmRpbGF0IikgfCBjb250YWlucyAoInN5bXBfY2FyZGlvdmFzY19hbmV1cnlzbSIpICB8Y29udGFpbnMoInN5bXBfY2FyZGlvdmFzY19zaG9jayIpKQoKYXNzb2Nfb3V0Y29tZV9mdWxsIDwtIG1lcmdlKG91dGNvbWVfcGFyYW1zLCBhc3NvY19vdXRjb21lLCBieSA9ICJwYXRpZW50SURfaW50IikKCmNvbHMgPC0gc2FwcGx5KGFzc29jX291dGNvbWVfZnVsbCwgaXMubG9naWNhbCkKYXNzb2Nfb3V0Y29tZV9mdWxsWyxjb2xzXSA8LSBsYXBwbHkoYXNzb2Nfb3V0Y29tZV9mdWxsWyxjb2xzXSwgYXMubnVtZXJpYykKCmFzc29jX291dGNvbWVfZnVsbCR1bmZhdm91cmFibGVfY291cnNlIDwtIGlmZWxzZShhc3NvY19vdXRjb21lX2Z1bGwkc3ltcF9jYXJkaW92YXNjX2NvcmRpbGF0ID09IDEgfCBhc3NvY19vdXRjb21lX2Z1bGwkc3ltcF9jYXJkaW92YXNjX2FuZXVyeXNtID09IDEgfCBhc3NvY19vdXRjb21lX2Z1bGwkc3ltcF9jYXJkaW92YXNjX3Nob2NrID09IDEgfCBhc3NvY19vdXRjb21lX2Z1bGwkb3V0Y29tZV9kZWF0aCA9PSAxIHwgYXNzb2Nfb3V0Y29tZV9mdWxsJGNyaXRjYXJlX01WID09IDEgfCBhc3NvY19vdXRjb21lX2Z1bGwkY3JpdGNhcmVfRUNNTyA9PSAxIHwgYXNzb2Nfb3V0Y29tZV9mdWxsJGNyaXRjYXJlX1JSVCA9PSAxIHwgYXNzb2Nfb3V0Y29tZV9mdWxsJGFkbWlzX1BJQ1VfYWRtaXMgPT0gMSB8IGFzc29jX291dGNvbWVfZnVsbCRjcml0Y2FyZV9pbm90cm9wID09IDEgLCAxLCAwKQoKYXNzb2Nfb3V0Y29tZV9mdWxsJG1pbGRfcHJlc2VudGF0aW9uIDwtIGlmZWxzZSgoYXNzb2Nfb3V0Y29tZV9mdWxsJHVuZmF2b3VyYWJsZV9jb3Vyc2UgPT0gMCB8IGlzLm5hKGFzc29jX291dGNvbWVfZnVsbCR1bmZhdm91cmFibGVfY291cnNlKSksIDEsIDApCgptYWtlVXBzZXRSKGFzc29jX291dGNvbWVfZnVsbCAlPiUgc2VsZWN0KGNvbnRhaW5zKCJjYXNlZGVmIikgfCBjb250YWlucygidW5mYXZvdXJhYmxlX2NvdXJzZSIpICkpCgoKbWFrZVVwc2V0Uihhc3NvY19vdXRjb21lX2Z1bGwgJT4lIHNlbGVjdChjb250YWlucygiY2FzZWRlZiIpIHwgY29udGFpbnMoInVuZmF2b3VyYWJsZV9jb3Vyc2UiKSAgfCBjb250YWlucygibWlsZF9wcmVzIikgKSkKCmBgYAoKIyMgUElDVSBjYW5kaWRhdGUKQSBuZXcgdmFyaWFibGUgJ1BJQ1UgY2FuZGlkYXRlJyBtYWRlLCB3aGljaCBjb250YWlucyB0aGUgZm9sbG93aW5nOgoKLSBzeW1wX2NhcmRpb3Zhc2Nfc2hvY2sgCi0gb3V0Y29tZV9kZWF0aAotIGNyaXRjYXJlX01WIAotIGNyaXRjYXJlX0VDTU8KLSBjcml0Y2FyZV9SUlQKLSBjcml0Y2FyZV9pbm90cm9wCi0gYWRtaXNfUElDVV9hZG1pcwoKTWlsZCBwcmVzZW50YXRpb24gbWVhbnMgYWxsIG9mIHRoZSBhYm92ZSBhcmUgZWl0aGVyIDAgb3IgTkEuIAoKYGBge3J9CmFzc29jX291dGNvbWUgPC0gbWVyZ2UoV0hPX291dGNvbWUsIENEQ19vdXRjb21lLCBieSA9ICJwYXRpZW50SURfaW50IikKYXNzb2Nfb3V0Y29tZSA8LSBtZXJnZShhc3NvY19vdXRjb21lLCBQSU1TX1RTX291dGNvbWUpCiNhc3NvY19vdXRjb21lIDwtIGFzc29jX291dGNvbWVbY29tcGxldGUuY2FzZXMoYXNzb2Nfb3V0Y29tZVsgLC0xXSksXQoKb3V0Y29tZV9wYXJhbXMgPC0gZGZfc2luZ2xlY2FzZXMgJT4lIHNlbGVjdChwYXRpZW50SURfaW50IHwgY29udGFpbnMoImNyaXRjYXJlIikgIHwgY29udGFpbnMoImFkbWlzX1BJQ1VfYWRtaXMiKSB8IGNvbnRhaW5zKCJvdXRjb21lX2RlYXRoIikgIHxjb250YWlucyAoInN5bXBfY2FyZGlvdmFzY19jb3JkaWxhdCIpIHwgY29udGFpbnMgKCJzeW1wX2NhcmRpb3Zhc2NfYW5ldXJ5c20iKSAgfGNvbnRhaW5zKCJzeW1wX2NhcmRpb3Zhc2Nfc2hvY2siKSkKCmFzc29jX291dGNvbWVfZnVsbCA8LSBtZXJnZShvdXRjb21lX3BhcmFtcywgYXNzb2Nfb3V0Y29tZSwgYnkgPSAicGF0aWVudElEX2ludCIpCgpjb2xzIDwtIHNhcHBseShhc3NvY19vdXRjb21lX2Z1bGwsIGlzLmxvZ2ljYWwpCmFzc29jX291dGNvbWVfZnVsbFssY29sc10gPC0gbGFwcGx5KGFzc29jX291dGNvbWVfZnVsbFssY29sc10sIGFzLm51bWVyaWMpCgphc3NvY19vdXRjb21lX2Z1bGwkUElDVV9jYW5kaWRhdGUgPC0gaWZlbHNlKCBhc3NvY19vdXRjb21lX2Z1bGwkc3ltcF9jYXJkaW92YXNjX3Nob2NrID09IDEgfCBhc3NvY19vdXRjb21lX2Z1bGwkb3V0Y29tZV9kZWF0aCA9PSAxIHwgYXNzb2Nfb3V0Y29tZV9mdWxsJGNyaXRjYXJlX01WID09IDEgfCBhc3NvY19vdXRjb21lX2Z1bGwkY3JpdGNhcmVfRUNNTyA9PSAxIHwgYXNzb2Nfb3V0Y29tZV9mdWxsJGNyaXRjYXJlX1JSVCA9PSAxIHwgYXNzb2Nfb3V0Y29tZV9mdWxsJGFkbWlzX1BJQ1VfYWRtaXMgPT0gMSB8IGFzc29jX291dGNvbWVfZnVsbCRjcml0Y2FyZV9pbm90cm9wID09IDEgLCAxLCAwKQoKYXNzb2Nfb3V0Y29tZV9mdWxsJG1pbGRfcHJlc2VudGF0aW9uIDwtIGlmZWxzZSgoYXNzb2Nfb3V0Y29tZV9mdWxsJFBJQ1VfY2FuZGlkYXRlID09IDAgfCBpcy5uYShhc3NvY19vdXRjb21lX2Z1bGwkUElDVV9jYW5kaWRhdGUpKSwgMSwgMCkKCm1ha2VVcHNldFIoYXNzb2Nfb3V0Y29tZV9mdWxsICU+JSBzZWxlY3QoY29udGFpbnMoImNhc2VkZWYiKSB8IGNvbnRhaW5zKCJQSUNVX2NhbmRpZGF0ZSIpICkpCgoKbWFrZVVwc2V0Uihhc3NvY19vdXRjb21lX2Z1bGwgJT4lIHNlbGVjdChjb250YWlucygiY2FzZWRlZiIpIHwgY29udGFpbnMoIlBJQ1VfY2FuZGlkYXRlIikgIHwgY29udGFpbnMoIm1pbGRfcHJlcyIpICkpCgpgYGAKCgojIFNlc3Npb25JbmZvCmBgYHtyfQpzZXNzaW9uSW5mbygpCmBgYA==